寫在前面:這裏是小王成長日誌,一名普通在校大學生,想成學習之餘將自己的學習筆記分享出來,記錄自己的成長軌跡,幫助可能需要的人,平時博客內容主要是一些學習筆記,項目實戰筆記,一些技術的探究和自己的一些思考。歡迎大家關注,你們的每一個評論點贊關注我都會仔仔細細去看的。有任何問題歡迎交流,我會盡我所能幫助大家的,共創CSDN美好環境。
一般來說,運算符優先級這種東西不應該去強行記憶,因爲在自己不確定的時候用括號來爲表達式強行指定順序就完事了,方便簡單不傷腦,而且在不同的語言中優先級也可能不同,用多了自然就熟了,但是!
直到看到一些題目,我才知道也許我們能夠控制自己,但是不能控制別人寫出那種毀天滅地的代碼,而且!老師也喜歡出那種花裏胡哨的題目,日常掉髮的程序猿繼續落淚~
1.速查表
供速查用,會不會都請先大致瀏覽一遍再看下面的。下面是一個文檔,內含C語言常用轉義字符、ASCII、優先級的對照表。(本來想直接上傳CSDN的,奈何審批太慢)
…發出來前幾秒,有提示我審覈通過了 點鏈接下載,不需要積分
鏈接:https://share.weiyun.com/5695tZw 密碼:7ytpbm
優先級 |
運算符 |
名稱或含義 |
使用形式 |
結合方向 |
說明 |
---|---|---|---|---|---|
1 |
[] |
數組下標 |
數組名[常量表達式] |
左到右 |
|
() |
圓括號 |
(表達式)/函數名(形參表) |
|||
. |
成員選擇(對象) |
對象.成員名 |
|||
-> |
成員選擇(指針) |
對象指針->成員名 |
|||
2 |
- |
負號運算符 |
-表達式 |
右到左 |
單目運算符 |
(類型) |
強制類型轉換 |
(數據類型)表達式 |
|||
++ |
自增運算符 |
++變量名/變量名++ |
單目運算符 |
||
-- |
自減運算符 |
--變量名/變量名-- |
單目運算符 |
||
* |
取值運算符 |
*指針變量 |
單目運算符 |
||
& |
取地址運算符 |
&變量名 |
單目運算符 |
||
! |
邏輯非運算符 |
!表達式 |
單目運算符 |
||
~ |
按位取反運算符 |
~表達式 |
單目運算符 |
||
sizeof |
長度運算符 |
sizeof(表達式) |
|||
3 |
/ |
除 |
表達式/表達式 |
左到右 |
雙目運算符 |
* |
乘 |
表達式*表達式 |
雙目運算符 |
||
% |
餘數(取模) |
整型表達式/整型表達式 |
雙目運算符 |
||
4 |
+ |
加 |
表達式+表達式 |
左到右 |
雙目運算符 |
- |
減 |
表達式-表達式 |
雙目運算符 |
||
5 |
<< |
左移 |
變量<<表達式 |
左到右 |
雙目運算符 |
>> |
右移 |
變量>>表達式 |
雙目運算符 |
||
6 |
> |
大於 |
表達式>表達式 |
左到右 |
雙目運算符 |
>= |
大於等於 |
表達式>=表達式 |
雙目運算符 |
||
< |
小於 |
表達式<表達式 |
雙目運算符 |
||
<= |
小於等於 |
表達式<=表達式 |
雙目運算符 |
||
7 |
== |
等於 |
表達式==表達式 |
左到右 |
雙目運算符 |
!= |
不等於 |
表達式!= 表達式 |
雙目運算符 |
||
8 |
& |
按位與 |
表達式&表達式 |
左到右 |
雙目運算符 |
9 |
^ |
按位異或 |
表達式^表達式 |
左到右 |
雙目運算符 |
10 |
| |
按位或 |
表達式|表達式 |
左到右 |
雙目運算符 |
11 |
&& |
邏輯與 |
表達式&&表達式 |
左到右 |
雙目運算符 |
12 |
|| |
邏輯或 |
表達式||表達式 |
左到右 |
雙目運算符 |
13 |
?: |
條件運算符 |
表達式1? 表達式2: 表達式3 |
右到左 |
三目運算符 |
14 |
= |
賦值運算符 |
變量=表達式 |
右到左 |
|
/= |
除後賦值 |
變量/=表達式 |
|||
*= |
乘後賦值 |
變量*=表達式 |
|||
%= |
取模後賦值 |
變量%=表達式 |
|||
+= |
加後賦值 |
變量+=表達式 |
|||
-= |
減後賦值 |
變量-=表達式 |
|||
<<= |
左移後賦值 |
變量<<=表達式 |
|||
>>= |
右移後賦值 |
變量>>=表達式 |
|||
&= |
按位與後賦值 |
變量&=表達式 |
|||
^= |
按位異或後賦值 |
變量^=表達式 |
|||
|= |
按位或後賦值 |
變量|=表達式 |
|||
15 |
, |
逗號運算符 |
表達式,表達式,… |
左到右 |
從左向右順序運算 |
2.記憶方法
開始記憶之前我們先來看一下一些表中涉及到的概念:
什麼是目?
所謂"目",也可以稱之爲元,那麼我們再來看看,單元(一元)運算符,雙元運算符,三元運算符,再看看例如看看下面幾個表達式,有沒有點感覺?
a++;// ++ 單目
&b;//& 單目
c - d;//- 雙目
e > f;//> 雙目
(1 > 2) ? a : b,//?: 三目
單目運算符, 一些只需要一個操作數的運算符稱爲一元運算符(或單目運算符),以此類推,雙目運算符有需要兩個操作數數才能進行運算.三元則需要三個(參考百度百科)
C語言中大部分都是雙目運算符,小部分是單目的,三目運算符只有一個,就是條件運算符 ?:
結合方向是什麼?
在上面的表裏,我們還能看到特殊的一列,就是結合方向,這一列指得是當運算符有優先級相同(同級)時的運算順序.
巧記方法
其實我也不想記,想在使用中熟悉,想着加括號就好,但是牢不住老師太猛啊,還是乖乖記一下吧:
- 1,記住總表的規律
- C語言中大多數運算符的結合性都是從左往右,只有三個運算符是從右往左的。一個是單目運算符,另一個是三目運算符,還有一個就是雙目運算符中的賦值運算符
=
。 - 雙目運算符中只有賦值運算符的結合性是從右往左的,其他的都是從左往右。
- C語言中有且只有一個三目運算符。
- 逗號運算符的優先級最低,要記住。
- 此外要記住,對於優先級:算術運算符 > 關係運算符 > 邏輯運算符 > 賦值運算符。邏輯運算符中“邏輯非 !”除外。
- C語言中大多數運算符的結合性都是從左往右,只有三個運算符是從右往左的。一個是單目運算符,另一個是三目運算符,還有一個就是雙目運算符中的賦值運算符
2.背一段順口溜
這是我在網上找的一段順口溜,背下來應該也是有用的
醋罈酸味灌
味落跳福豆
共44個運算符:
醋 | 初等,4個:()[]->指向結構體成員.結構體成員 |
壇 | 單目,9個:!~+±–負號(類型)*指針&取地址sizeof長度 |
酸 | 算術,5個:*/%±減 |
味 | 位移,2個:<<>> |
灌 | 關係,6個:<<=>>===等於!=不等於 |
味 | 位邏,3個:&按位與^按位異或|按位或 |
落 | 邏輯,2個:&&邏輯與||邏輯或 |
跳 | 條件,1個,三目:?: |
福 | 賦值,11個:=+=-=*=/=%=>>=<<=&=^=|= |
豆 | 逗號,1個:, |
簡單記就是:! > 算術運算符 > 關係運算符 > && > || > 賦值運算符
參考:
3.一起看看運算符優先級的一些題目
1. C語言混亂代碼大賽-嘗試理解一下下面這段代碼
#include <stdio.h>
char *a; main(int t,int _,char* a){return!0<t?t<3?main(-79,-13,a+main(-87,1-_, main(-86,0,a+1)+a)):1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13? main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t, "@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/") :t<-50?_==*a?putchar(31[a]):main(-65,_,a+1):main((*a=='/')+t,_,a+1) :0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a, "!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);}
能力有限,我就不班門弄斧了,而且這個遠遠不止於運算符優先級,感興趣的同學可以點上面的超鏈接去看看
2. *p++自增p還是p所指向的變量?
在這一題中,根據我們的理解,* 的優先級是要低於 自增符++的,所以 *p++ 實際上和 *(p++) 等價,它自增p並且返回p自增之前所指向的值。
如果我們想要自增p所指向的值則需要寫成 (*p)++;
看代碼:
int *p = NULL;
int arr[2] = {1, 10};
p = arr;
printf("*p++ = %d\n",*p++);//1
printf("*p = %d\n",*p);//10
p = arr;
printf("(*p)++ = %d\n",(*p)++);//1
printf("*p = %d\n",*p);//2
3. 試着理解a+++++b
在C中,寫成這樣也是沒有意義的。詞彙分析的規則規定,在一個簡單的從左到右掃描中的每個點,最長的記號被劃分,不管這樣出來的記號序列是否有意義。問題中的片段被解釋爲
a ++ ++ +
在語法上說這是個不合法的表達式
經提醒 在JAVA中這樣寫是合法的,注意區分
看代碼
int a,b;
a=1;
b=2;
printf("a+++++b = %d",a+++++b);
/**************運行結果
test.c: In function 'main':
test.c:9:30: error: lvalue required as increment operand
printf("a+++++b = %d",a+++++b);
**************/
4. k = j>i && 8==i;
岔看到這個表達式的時候會不會有點頭暈,因爲我們日常都會在不明確的地方加上括號,例如
( k = j )&&( 8 == i )
但是在這個表達式中沒有任何括號給我們提示,並且涉及到了四種運算符,其優先級都需要我們自己去考慮。
首先速查這四種運算符的優先級:
賦值運算符優先級最低,其次&&AND運算符,== 和 > 雖然都是雙目運算符,但是== 優先級低於 > 運算符。
所以上式等同於
(k = (j > i)) && (8 == i)看代碼:
int k, j, i;
k = 1;
j = 2;
i = 8;
printf("%d\n",j > i);//0
printf("%d\n",k = (j > i));//0
printf("%d\n",8 == i);//1
printf("(k = (j > i)) && (8 == i) = %d\n", (k = (j > i)) && (8 == i));//0
printf("k = j > i && 8 == i = %d", k = j > i && 8 == i);//0
4.參考
- 詳見原文超鏈接
5.以往文章推薦
都看到這裏了,各位哥哥姐姐叔叔阿姨給小王點個贊 關個注 留個言吧,和小王一起成長吧,你們的關注是對我最大的支持。
如果以上內容有任何不準確或遺漏之處,或者你有更好的意見,就在下面留個言讓我知道吧-我會盡我所能來回答。