C語言學習及應用筆記之一 C運算子優先順序及使用問題

2022-06-20 16:33:10 字數 4182 閱讀 7751

c語言中的運算子絕對是c語言學習和使用的乙個難點,因為在2011版的標準中,c語言的運算子的數量超過40個,甚至比關鍵字的數量還要多。這些運算子有單目運算子、雙目運算子以及三目運算子,又涉及到左結合和右結合的問題,真是令人眼花繚亂。

1、運算子及優先順序

運算子多可能使用更靈活方便,但這還涉及到運算子之間的優先順序問題。我們做四則表示式時,有先乘除後加減的規定,在c語言的這些運算子中自然也是有的,但40多個運算子排起優先順序來,使用就不那麼容易了。

接下來我們簡單的總結一下c語言中運算子以及他們的優先順序。c語言中各運算子的優先順序如下表所示:

優先順序

運算子

名稱或含義

使用形式

結合方向

說明1

陣列下標

陣列名[常量表示式]

左到右()

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

.成員選擇(物件)

物件.成員名

->

成員選擇(指標)

物件指標->成員名

++後置自增運算子

++變數名

單目運算子

--後置自減運算子

--變數名

單目運算子2-

負號運算子

-表示式

右到左單目運算子

(型別)

強制型別轉換

(資料型別)表示式

++前置自增運算子

變數名++

單目運算子

--前置自減運算子

變數名--

單目運算子

*取值運算子

*指標變數

單目運算子

&取位址運算子

&變數名

單目運算子

!邏輯非運算子

!表示式

單目運算子

~按位取反運算子

~表示式

單目運算子

sizeof

長度運算子

sizeof(表示式)3/

除表示式/表示式

左到右雙目運算子*乘

表示式*表示式

雙目運算子

%餘數(取模)

整型表示式/整型表示式

雙目運算子4+

加表示式+表示式

左到右雙目運算子-減

表示式-表示式

雙目運算子

5<

左移變數《表示式

左到右雙目運算子

>> 

右移變數》表示式

雙目運算子

6> 

大於表示式》表示式

左到右雙目運算子

>=

大於等於

表示式》=表示式

雙目運算子

小於表示式《表示式

雙目運算子

<=

小於等於

表示式<=表示式

雙目運算子7==

等於表示式==表示式

左到右雙目運算子

!=不等於

表示式!= 表示式

雙目運算子8&

按位與表示式&表示式

左到右雙目運算子9^

按位異或

表示式^表示式

左到右雙目運算子10|

按位或表示式|表示式

左到右雙目運算子

11&&

邏輯與表示式&&表示式

左到右雙目運算子

12||

邏輯或表示式||表示式

左到右雙目運算子

13?:

條件運算子

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

右到左三目運算子14=

賦值運算子

變數=表示式

右到左/=

除后賦值

變數/=表示式

*=乘後賦值

變數*=表示式

%=取模後賦值

變數%=表示式

+=加後賦值

變數+=表示式

-=減後賦值

變數-=表示式

<<=

左移後賦值

變數<<=表示式

>>=

右移後賦值

變數》=表示式

&=按位與後賦值

變數&=表示式

^=按位異或後賦值

變數^=表示式

|=按位或後賦值

變數|=表示式15,

逗號運算子

表示式,表示式,…

左到右從左向右順序運算

在上表中,我們歸納了運算子、個運算子的功能、通常的應用表示式形式以及結合性。說到結合性主要應用於相同優先順序的運算子,運算次序由結合方向所決定。絕大部分的運算子都是左結合的,與我們的常識一致。不過有一部分運算子是右結合的,這些就需要記憶了,但記憶有時候卻不見得百分百準確,所以我們可以在編寫**時以( )加以規範。

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<

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

i=1,2

i=(1,2)

(i=1),2

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

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

優先順序問題經常會造成一些意想不到的結果,有的甚至是非常嚴重的。本人在編寫程式時,就出現過一些因為疏忽運算子優先順序造成的問題,而且檢查起來非常不容易發現。

例如,有一次,我們採集了感測器的原始資料,然後會對資料進行一些處理,在其中的一種條件下會對乙個數進行左移幾位並加上乙個數。由於算術運算子的優先順序大於移位運算子,而程式設計師忘記了給移位操作加括號,所以得出了結果總是有誤,只好從頭開始查詢,花了不少時間才發現這齣錯誤。如msb<<4+lsb和(msb<<4)+lsb是完全不一樣,因為算術運算子的優先順序大於移位運算子。

還有一次,我們定義乙個指向函式的指標陣列用於**函式的操作。定義時,沒有考慮到指標運算子、函式運算子以及陣列運算子的優先順序問題而造成呼叫出錯。如,void (*p)f()的形式,如果寫成void *pf()的形式就完全錯誤了。

當然,如果能夠熟記各種運算子的優先順序也許能解決上面的問題,但這實際上卻很難達到,因為應用是非常靈活的,你不可能時時刻刻只關注於此。我覺得養成良好的編碼習慣以及多多練習似乎更有效。

C語言學習筆記(一)

c 語言只提供了以下幾種基本資料型別 char 字元刑占用乙個位元組,可以存放本地字符集中的乙個字元 int整型 通常反應了所用機器中整數的自然長度 float 單精度浮點型 doule 雙精度浮點型 此外,可以在這些基本資料型別的錢買年加上些限定符。short 與long 兩個限定符用於限定整型 ...

C語言學習筆記(一)

進製問題 1 進製 2進製 8進製 10進製 16進製制 2進製 進製規則是逢二進一,1 二進位制轉十進位制 方法 按權展開求和 二進位制怎麼會有小數點 例 規律 個位上的數字的次數是0,十位上的數字的次數是1,依次遞增,而十 分位的數字的次數是 1,百分位上數字的次數是 2,依次遞減。注意 不是任...

C語言學習筆記(一)

預處理指令 巨集定義 define,undef 檔案包含 include 條件編譯 ifdef,if,elif,else,endif define disk capacity sides tracks per side sectors per track bytes per sector 對於帶引數...