在本節中,我們來一起學習操作符的優先級,並且需要了解在相同優先級下的操作符的結合性。我們先來看一下操作符優先級和結合性的表格:
級別(由高到低) | 操作符(使用空格分隔) | 結合性 |
1 | () [] -> . | 由左向右 |
2 | ! ~ ++ -- + - * (type) sizeof | 由右向左 |
3 | * / % | 由左向右 |
4 | + - | 由左向右 |
5 | << >> | 由左向右 |
6 | < <= > >= | 由左向右 |
7 | == != | 由左向右 |
8 | & | 由左向右 |
9 | ^ | 由左向右 |
10 | | | 由左向右 |
11 | && | 由左向右 |
12 | || | 由左向右 |
13 | ?: | 由右向左 |
14 | = += -= *= /= %= &= ^= |= <<= >>= | 由右向左 |
15 | , | 由左向右 |
C語言中的操作符優先級一共分爲15級,當多個操作符出現在同一個表達式中時,需要按其優先級順序進行計算,優先級相同時按結合性進行計算。例如:我們編寫一個問號表達式,並在其條件表達式中這樣寫:
int a = 1;
int b = 2;
printf("%c\n", a | b == 5 ? 'T' : 'F');
printf("%c\n", (a | b) == 5 ? 'T' : 'F');
T
F
我們來分析一下上面程序的運行過程:
在第一個問號表達式中,由於 ?: 的優先級低,所以要先計算?前面的條件表達式的值,而對於 a | b == 5中 | 的優先級低於 == 的優先級,所以這個表達式的值應該是先比較 b == 5 的結果爲“真”,其值爲1,再將a與這個結果1做或運算,結果爲1。於是整個 a | b == 5 表達式的值爲1,所以在接下來的問號表達中的條件判斷時認爲其結果爲“真”,所以整個問號表達式的結果爲'T'。
在第二個問號表達式中,仍然需要優先計算 ? 前面的條件表達式,而對於 (a | b) == 5這個表達式中,小括號()的優先級高於 == 比較運算符,所以要先計算 a | b 的值,結果爲3,然後將3與5做比較運算即: 3 == 5,這個表達式的結果爲“假”,其值爲0,再將這個結果做爲後續問號表達式的條件判斷,所以問號表達式的結果爲'F'。
我們再來看一個例子:
int x = 2;
printf("%d %lf\n", ++x, pow(3, x));
3 9.000000
上面這段代碼在我的編譯器下運行的結果爲3和9.0,而在其它編譯器下,結果可能是3和27.0。所以爲了保證代碼的一致性和可讀性,我們應該將上面的代碼書寫這樣:
int x = 2;
++x;
printf("%d %lf\n", x, pow(3, x));
3 27.000000
我們再來看看使用自增運算符對數組做賦值操作的程序:
int a[3] = { 7, 8, 9 };
int i = 0;
a[i] = ++i;
對於上面代碼中對數組變量a[i]做賦值操作的賦值之後數組元素的值分別爲7、1、9。同樣在不同的編譯下,運行結果可能不同。所以在編寫代碼時要了解你的編譯器運行機制,並清楚的知道編譯器將如何處理這樣的程序代碼。當然好的程序應該儘量避免這樣對不同編譯器有不同運行結果的代碼,例如這樣來書寫:
int a[3] = { 7, 8, 9 };
int i = 0;
++i;
a[i] = i;
歡迎關注公衆號:編譯外星人