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 對於帶引數...