示例代碼:
#define X(x,y) x y
#define STR_(x) #x
#define STR(x) STR_(x)
STR(X(Y,Y))
呼叫:
$ gcc t222.c -std=c11 -pedantic -Wall -Wextra -E -P
"Y Y"
$ gcc t222.c -std=c11 -pedantic -Wall -Wextra -E -P -D"Y()"
"YY"
為什么 gcc 會洗掉預處理標記之間的空格?
例如,clang 不會:
$ clang t222.c -std=c11 -pedantic -Wall -Wextra -E -P -D"Y()"
"Y Y"
UPD1。不知何故 gcc 考慮到,和之間的空白Y:
$ gcc t222.c -std=c11 -pedantic -Wall -Wextra -E -P -D"Y()" -D"Z=STR(X(Y,Y))"
"YY"
$ gcc t222.c -std=c11 -pedantic -Wall -Wextra -E -P -D"Y()" -D"Z=STR(X(Y, Y))"
"Y Y"
UPD2。這:
STR(X(Y,
Y))
造成:
$ gcc t222.c -std=c11 -pedantic -Wall -Wextra -E -P -D"Y()"
"Y Y"
然而,這:
STR(X(Y
,Y))
造成:
$ gcc t222.c -std=c11 -pedantic -Wall -Wextra -E -P -D"Y()"
"YY"
UPD3。報告:https : //gcc.gnu.org/bugzilla/show_bug.cgi? id =104147。
uj5u.com熱心網友回復:
這是 GCC 中的一個錯誤。C 2018 6.10.3.2 指定#操作員的行為。第 1 段說“#類函式宏的替換串列中的每個預處理標記都應跟一個引數作為替換串列中的下一個預處理標記。” 我們認為,這在#x的#define STR_(x) #x。
第 2 段說:
如果在替換串列中,引數前面緊跟
#預處理標記,則兩者都被單個字串文字預處理標記替換,該預處理標記包含對應引數的預處理標記序列的拼寫。引數的預處理標記之間每次出現的空白都會成為字串文字中的單個空格字符。洗掉第一個預處理標記之前和組成引數的最后一個預處理標記之后的空白......
X(Y,Y)宏呼叫必須產生標記Y和,Y我們看到#define X(x,y) x y它們之間會有空格。
根據 6.10.3 1,宏替換串列中的空白很重要,它說:
當且僅當兩個替換串列中的預處理標記具有相同的編號、排序、拼寫和空格分隔符時,兩個替換串列是相同的,其中所有空格分隔符都被認為是相同的。
因此,在 中#define X(x,y) x y,替換串列不應被視為只是兩個標記x和y,而忽略空格。替換串列是x、空格和y。
此外,當宏被替換時,它被替換串列(因此包括空格)替換,而不僅僅是替換串列中的標記,根據 6.10.3 10:
...類函式宏名稱的每個后續實體后跟
(作為下一個預處理標記的 a 引入了預處理標記的序列,該序列被定義中的替換串列替換(宏的呼叫)...在預處理標記的序列中在呼叫類似函式的宏時,換行符被認為是正常的空白字符。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/417893.html
標籤:
