C語言中++、-- 及編譯器的貪心法
阿新 • • 發佈:2018-12-14
C語言中的++、–即自增、自減是很令人頭疼的。 剛好看到一個問題,一起分析一下。
int i = 3;
(++i) + (++i) + (++i);
你覺得這個表示式的值是多少? 如果你覺得是15,那完了,你c語言學的跟我一樣,太爛了。 我去查了一下,有說是16,還有說是18的。分析了一下,好像都有道理。 如果是都先做完括號內的,那答案就是18了。 但編譯器如果認為前兩個括號做完,然後會認為後面是加號,和前面一樣的,前面兩個便可以先進行計算,結果就是16。 分析完了,就直接去執行看結果吧,我使用了gcc和g++編譯,結果都是16。後來問大佬,查資料,據說這是c語言的灰色地帶,沒有明確規定,結果會因編譯器規則不同而不同。
繼續看另一段程式碼:
#include <stdio.h>
int main()
{
int i = 0;
int j = ++i+++i+++i;//報錯1
int a = 1;
int b = 2;
int c = a+++b;
int* p = &a;
b = b/*p;//報錯2
return 0;
}
你覺得j的結果是多少? 實際是這裡會報錯,
[Error] lvalue required as increment operand
說左值不可以增運算,為什麼報這錯呢?因為編譯器是貪心法閱讀
修改之後,再編譯,發現上面的第二個報錯,這個又為什麼報錯呢,如果用ide編輯程式碼,就會發現從/*開始都認為是註釋了。就是我們之前提到的編譯器的貪心法了,認為是註釋開頭了。
對此,通常程式設計規範中都會有規定,對於運算都明確加括號以明確運算順序。另外就是我們會發現,使用很多ide程式設計的時候,在我們例如加上結束符之後,會幫我們格式化,這時你都會發現運算物件和運算子之間都會有空格,其實這不光光是美觀,編譯器會識別空格,知道這裡是讀入結束。 瞭解了這些知識,修改上面的程式碼:
#include <stdio.h>
int main()
{
int i = 0;
int j = ++i+ ++i+ ++i;
int a = 1;
int b = 2;
int c = a+++b;
int* p = &a;
b = b/ *p;
return 0;
}
不光看的清晰,編譯執行完美了。