標籤:

#define 不是簡單的替換嗎,為什麼下面的代碼錯誤?

#define OP *
int main()
{
int a = 3;
a OP= 3;
// a *= 3 ??
return 0;
}


#define 的替換是在「詞語」的層面進行的,所以替換結果是類似於「a * = 3」(注意那個空格),當然出問題了


你把代碼展開就知道了,存為test.c文件,然後使用cpp處理一下,得到的結果:

ma@ma-T440p:~$ cpp test.c
# 1 "test.c"
# 1 "&"
# 1 "&"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "&" 2
# 1 "test.c"

int main()
{
int a = 3;
a * = 3;

return 0;
}

這就一目了然了么。


是詞法分析後替換,而不是文本替換

實際替換規則還是有點複雜的,比如可變參,遞歸替換等


預處理(宏展開)是在詞法分析做完之後實施的,詞法分析後的結構是一個一個的token,此時OP和=是兩個token,宏展開後依然是兩個token。而如果沒有用宏而是寫成*=,詞法分析會把他們識別成一個token,即乘等操作符。希望題主能夠理解這個意思。

更新一發評論中的回答:

詞法分析器不是通過加空格來劃分token的(事實上不做詞法分析他又怎麼知道要在哪裡加空格呢?),他有自己的一套規則。對你這個例子,他遇到O後會認為這是一個標識符token的開頭(標識符是字母數字下劃線組合,且不能數字開頭),繼續往前找直到遇到一個不滿足標識符規則的字元,=不滿足所以斷到=前面,如果是空格也是一樣斷,於是識別出的token是一個內容為OP的標識符。同樣的道理,如果你寫的是OPabcd,那麼就會斷到d後面,然後識別出的token就是一個內容為OPabcd的標識符,結果就是你並不會看到他被展開成*abcd。以上要說的就是宏展開是基於詞法分析得到的token流而不是直接在原始C代碼上做的簡單字元替換。

最後教你一招:

#define OP(o) *##o

使用時,如果想用乘等:

a OP(=) b;

如果想用乘:

c = a OP() b;

gcc上可以,不保證別的編譯器也能編過。

手機敲代碼累死。。。


可以用-traditional-cpp強行編(純種gcc,clang的不行)

% cat test.c

#define OP +

void main(void) {

int i = 10;

i OP= 1;

printf("%d
", i);

}

% gcc -traditional-cpp test.c -o test

test.c: In function "main":

test.c:6:5: warning: implicit declaration of function "printf" [-Wimplicit-function-declaration]

printf("%d
", i);

^

test.c:6:5: warning: incompatible implicit declaration of built-in function "printf"

test.c:6:5: note: include "&" or provide a declaration of "printf"

% ./test

11


% cat 1.c
#define OP *
int main()
{
int a = 3;
a OP= 3;
return 0
}

% gcc -E 1.c
# 1 "1.c"
# 1 "&" 1
# 1 "&" 3
# 329 "&" 3
# 1 "&" 1
# 1 "&" 2
# 1 "1.c" 2

int main()
{
int a = 3;
a * = 3;
return 0
}

% cat 2.c
#define CONCAT_OP(op1, op2) op1 ## op2
int main()
{
int a = 3;
a CONCAT_OP (*, =) 3;
return 0
}

% gcc -E 2.c
# 1 "2.c"
# 1 "&" 1
# 1 "&" 3
# 329 "&" 3
# 1 "&" 1
# 1 "&" 2
# 1 "2.c" 2

int main()
{
int a = 3;
a *= 3;
return 0
}


推薦閱讀:

當把一個char類型轉換成int型的時候計算機里究竟而發生了什麼?
OpenMP在實際開發中應用多嗎?
對於 C/C++ 函數指針的困惑?
有沒有使用「==」判斷浮點數相等與否出現錯誤的例子?
怎樣開發一款有限元軟體,從哪些方面學習?

TAG:C | CC |