[英]Is it possible to define another preprocessor directive?
我一直在尋找代碼高爾夫,並有一個想法嘗試這個代碼:
#define D #define
添加此行后,一切正常,但我將其擴展為:
#define D #define
D VALUE
在這里我得到了5個編譯錯誤。 如果我把D
改成#define
一切都很好,有人可以解釋,為什么這段代碼是非法的?
注意:我使用的是VS2008編譯器。
編輯:經過一些答案,我看到我需要給出編譯錯誤列表:
第一個錯誤顯示D
不僅僅是define
,還包括#
。
C 2011(N1570)6.10.3.4 3:“得到的完全宏替換的預處理標記序列不會被處理為預處理指令,即使它類似於一個......”
C ++ 2010(N3092)16.3.4 [cpp.rescan] 3具有完全相同的文本。
看起來您的預處理器正在進行您想要的替換,但您可能無法獲得所需的行為 - 預處理器通常只是單個傳遞操作。 示例(使用clang,但您應該能夠使用適當的VS2008標志重現):
$ cat example.c
#define D #define
D VALUE
$ cc -P -E example.c
#define VALUE
#define VALUE
直接進入編譯器,編譯器不知道如何處理它 - 畢竟它是一個預處理器指令。 Clang的錯誤,供參考,與您的相似:
$ cc -c example.c
example.c:2:1: error: expected identifier or '('
D VALUE
^
example.c:1:11: note: expanded from macro 'D'
#define D #define
^
1 error generated.
此代碼是非法的,因為語言規范說它是非法的。 根據C和C ++預處理器規范,使用預處理器構建的任何代碼都不會被解釋為另一個預處理器指令。 簡而言之,您無法使用預處理器構建預處理程序指令。 期。
(另外,您無法使用預處理器構建注釋。)
這是行不通的,因為預處理是在一次通過中執行的。 例如,考慮下一個代碼:
#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6
int main() {
return 0;
}
預處理后,您的代碼將如下所示:
#define N 6
int main() {
return 0;
}
和“#define”不是C或C ++上的有效語法。 此外,由於不會處理生成的預處理程序指令,因此它不會解析代碼中對“N”宏的后續引用。
只是為了好玩,您可以使用g ++ / gcc從命令行調用預處理器兩次。 考慮下一個代碼(define.cpp):
#include <iostream>
#define MYDEFINEWEIRD #define
MYDEFINEWEIRD N 6
using namespace std;
int main() {
cout << N << endl;
return 0;
}
然后你可以這樣做:
$ g++ -E define.cpp | g++ -o define -x c++ - && ./define
並將輸出:
6
預處理器眼中的代碼行是預處理器語句(因此沒有對它們進行任何替換)或正常的文本語句(並且已經完成替換)。 你不能同時擁有一個,所以一旦你'D'被替換,它只會查看是否還有更多的宏需要替換。 由於沒有,它只是在C ++代碼中留下'#define',然后C ++編譯器在看到它時會出錯(因為'#define'不是有效的C ++代碼)。
所以更多地表明我的觀點,這是預處理器的無效代碼:
#define D define
#D value
因為預處理器不對預處理器語句進行任何宏替換,並且“#D”不是可識別的預處理器命令。 和這個:
#define D #define
D value
結果在這個C ++代碼中:
#define value
這是無效的,因為預處理器已經完成運行。
查看16 [cpp]段1中的語法, 替換列表由pp-tokens組成,其中可包括生產#no-directive ,該指令在同一段的第2段中描述為
非指令不應以列表中出現的任何指令名開頭。
也就是說,某種形式
#define NAME # define
恰好是非法的! 另請注意,此上下文中的#
不會將下一個單詞轉換為字符串: #
只會在#
函數樣式宏中緊跟一個宏參數名后發生。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.