C語言應用筆記(一) 運算子優先順序和使用問題

2021-10-03 20:56:10 字數 4622 閱讀 8450

c 語言運算子是說明特定操作的符號,它是構造 c 語言表示式的工具。c 語言的運算異常豐富,除了控制語句和輸入輸出以外的幾乎所有的基本操作都為運算子處理。除了常見的三大類,算術運算子、關係運算子與邏輯運算子之外,還有一些用於完成特殊任務的運算子,比如位運算子。

c 語言中的運算子絕對是 c 語言學習和使用的乙個難點,因為在2011版的標準中,c 語言的運算子的數量超過40個,甚至比關鍵字的數量還要多。

1、運算子及優先順序

運算子多的好處之一是使用靈活方便,但這涉及到運算子之間的優先順序問題。比如做四則運算時,有先乘除後加減的規定,但是 c 語言中的運算子已經遠不止四則運算中的加減乘除了,還有其他很多運算子。當它們出現在同乙個表示式中時先計算誰後計算誰呢?

c 語言中各運算子的優先順序如下表:

優先順序

運算子

名稱或含義

使用形式

結合方向

說明1

陣列下標

陣列名[常量表示式]

左到右()

圓括號(表示式)/函式名(形參表) .

成員選擇(物件)

物件.成員名

->

成員選擇(指標)

物件指標->成員名 ++

後置自增運算子

++變數名

單目運算子 --

後置自減運算子

--變數名

單目運算子 2

-負號運算子

-表示式

右到左單目運算子

(型別)

強制型別轉換

(資料型別)表示式 ++

前置自增運算子

變數名++

單目運算子 --

前置自減運算子

變數名--

單目運算子 *

取值運算子

*指標變數

單目運算子 &

取位址運算子

&變數名

單目運算子 !

邏輯非運算子

!表示式

單目運算子 ~

按位取反運算子

~表示式

單目運算子

sizeof

長度運算子

sizeof(表示式) 3

/ 除表示式/表示式

左到右雙目運算子 *

乘表示式*表示式

雙目運算子 %

餘數(取模)

整型表示式/整型表示式

雙目運算子 4

+ 加表示式+表示式

左到右雙目運算子 -

減表示式-表示式

雙目運算子 5

<<  左移

變數《表示式

左到右雙目運算子

>>  右移

變數》表示式

雙目運算子 6

>  大於

表示式》表示式

左到右雙目運算子

>=

大於等於

表示式》=表示式

雙目運算子

<  小於

表示式《表示式

雙目運算子

<=

小於等於

表示式<=表示式

雙目運算子 7

== 等於

表示式==表示式

左到右雙目運算子 !=

不等於表示式!= 表示式

雙目運算子 8

&按位與

表示式&表示式

左到右雙目運算子 9

^按位異或

表示式^表示式

左到右雙目運算子 10

|按位或

表示式|表示式

左到右雙目運算子 11

&&邏輯與

表示式&&表示式

左到右雙目運算子 12

||邏輯或

表示式||表示式

左到右雙目運算子 13

?:條件運算子

表示式1? 表示式2:  表示式3

右到左三目運算子 14

=賦值運算子

變數=表示式

右到左/=

除后賦值

變數/=表示式 *=

乘後賦值

變數*=表示式 %=

取模後賦值

變數%=表示式 +=

加後賦值

變數+=表示式 -=

減後賦值

變數-=表示式

<<=

左移後賦值

變數<<=表示式

>>=

右移後賦值

變數》=表示式 &=

按位與後賦值

變數&=表示式 ^=

按位異或後賦值

變數^=表示式 |=

按位或後賦值

變數|=表示式 15

,逗號運算子

表示式,表示式,…

左到右從左向右順序運算

上表中可以總結出如下規律:

結合方向只有三個是從右往左,其餘都是從左往右。

所有雙目運算子中只有賦值運算子的結合方向是從右往左。

另外兩個從右往左結合的運算子也很好記,因為它們很特殊:乙個是單目運算子,乙個是三目運算子。

c 語言中有且只有乙個三目運算子。

逗號運算子的優先順序最低,要記住。

此外要記住,對於優先順序:算術運算子 > 關係運算子 > 邏輯運算子 > 賦值運算子。邏輯運算子中 「邏輯非 !」 除外。

2、優先順序的一些特別說明

上表中,優先順序同為 1 的幾種運算子如果同時出現,那怎麼確定表示式的優先順序呢?這是很多初學者迷糊的地方。例如我們常常對指向多維陣列的指標和指標陣列,還有指向函式的指標陣列等含混不清,對初學者來說就更是迷惑不解。所以在這樣的定義表示式中,如果優先順序不明確結果有可能相去甚遠。

優先順序問題

表示式

想要的結果

實際結果

.的優先順序高於*

*p.f

指標p所指向的物件的某一欄位f,即:(*p).f

對p取f偏移作為指標,然後進行解除飲用操作,即:*(p.f)

的優先順序高於*

int  *p

p是指向int陣列的指標,即:int  (*p)

p是元素為指向int的指標的陣列,即:int  *(p)

函式()優先順序高於*

int  *p()

p是個函式指標所指函式返回值是int,即:int  (*p)()

p是個函式,返回值是int  *,即:int *(p())

==和!=優先順序高於位操作

(val&mask!=0)

(val&mask)!=0

val&(mask!=0)

==和!=優先順序高於賦值操作

c=getchar()!=eof

(c=getchar())!=eof

c=(getchar()!=eof)

算術運算子高於移位運算子

msb<<4+lsb

(msb<<4)+lsb

msb<<(4+lsb)

逗號運算子的優先順序最低

i=1,2

i=(1,2)

(i=1),2

那麼是不是有了上面的總結就穩妥了呢?當然不可能,且不說我們的總結很不完備,就算記住了所有的規則,在使用過程中仍然有可能漏洞百出,最好的辦法是養成良好的編碼習慣!

3、由優先順序引發的錯誤

優先順序問題經常會造成一些意想不到的結果,有的甚至非常嚴重,而且很難察覺到哪個地方運算子的優先順序存在錯誤。當然,如果能夠熟記各種運算子的優先順序也許能夠避免由運算子的優先順序引發的問題,但實際上是很難達到的,c 語言的運算子運用非常靈活,編碼的時候不可能時刻關注其優先順序。

而且事實上在程式設計的時候也不需要考慮優先順序的問題。因為如果不知道優先順序高低的話,加乙個括號就可以了,因為括號( )的優先順序是最高的。

簡而言之,首先,不需要專門記憶,也沒有必要。因為作為初學者,哪個優先順序高、哪個優先順序低我們很難記住。就算死記硬背記住了,時間長不用也會忘記。所以當乙個表示式中有多個運算子時,如果不知道哪個優先順序高哪個優先順序低就查一下優先順序表。用的時間長了自然而然就記住了,這樣記才會記得深刻。

其次,還是養成良好的編碼習慣和多用多練更靠譜。一定要多除錯,光靠看**,水平是很難提上來的。

附c語言運算子優先順序口訣:

括號成員第一; //括號運算子 () 成員運算子 . ->

全體單目第二; //所有的單目運算子比如 ++、--、+(正)、-(負)、指標運算*、&乘除餘三,加減四; 這個"餘"是指取餘運算即 %

移位五,關係六; //移位運算子:<< >>,關係:> < >= <= 等

等於(與)不等排第七; //即 == 和 !=

位與異或和位或; //這幾個都是位運算: 位與 & 、異或 ^ 、位或 |

"三分天下"**十;

邏輯或跟與; //邏輯運算子:|| 和 &&

十二和十一; //注意順序:優先順序(||) 低於 優先順序(&&)

條件高於賦值; //三目運算子優先順序排到 13 位只比賦值運算子和","高

逗號運算級最低; //逗號運算子優先順序最低

運算子優先順序 C 運算子優先順序

c 運算子優先順序 優先順序運算子 描述方向1 scope resolution 範圍解析 left to right 2 suffix postfix increment and decrement 字首 字尾遞增和遞減 function call 函式呼叫 array subscripting ...

C語言運算子優先順序

優先順序運算子 名稱或含義 使用形式 結合方向說明1 陣列下標 陣列名 常量表示式 左到右 圓括號 表示式 函式名 形參表 成員選擇 物件 物件.成員名 成員選擇 指標 物件指標 成員名2 負號運算子 表示式 右到左單目運算子 型別 強制型別轉換 資料型別 表示式 自增運算子 變數名 變數名 單目運...

c語言運算子優先順序

優先順序運算子 名稱或含義 使用形式 結合方向說明1 陣列下標 陣列名 常量表示式 左到右 圓括號 表示式 函式名 形參表 成員選擇 物件 物件.成員名 成員選擇 指標 物件指標 成員名2 負號運算子 表示式 右到左單目運算子 型別 強制型別轉換 資料型別 表示式 自增運算子 變數名 變數名 單目運...