One*_*ero 65 macros c-preprocessor
1. #define NUM 10
2. #define FOO NUM
3. #undef NUM
4. #define NUM 20
5.
6. FOO
Run Code Online (Sandbox Code Playgroud)
当我只运行预处理器时,输出文件包含20.
但是,根据我的理解,预处理器只是简单地替换文本.所以这就是我认为正在发生的事情(这显然是错误的但是很蠢):
所以我认为输出应该是10而不是20.可以解释它出错的地方吗?
Dav*_*vid 64
文本替换是在使用宏的地方完成的,而不是在你写的地方#define.在您使用的点FOO,它会替换FOO与NUM和NUM目前定义为20.
ric*_*ici 57
为了从标准中收集所有相关规范,我从评论主题中提取了这些信息,并根据草案N4527添加了C++部分编号(规范性文本在两个标准中是相同的).标准在这个主题上是绝对清楚的.
#define 预处理程序指令不进行宏替换.
(C11§6.107; C++§16[cpp]6):除非另有说明,否则预处理指令中的预处理标记不受宏扩展的影响.
用替换文本替换宏后,将重新扫描新文本.如果在程序中该点处存在令牌的活动宏定义,则替换中的预处理器令牌将扩展为宏.
(C11§6.10.39; C++§16.3[cpp.replace]9)表格的预处理指令
# define identifier replacement-list new-line定义一个类似于对象的宏,它使宏名称的每个后续实例都被构成指令其余部分的预处理标记的替换列表替换.然后重新扫描替换列表以获取更多宏名称,如下所示.
宏定义是位于有源从继线#define,直到#undef对宏名称,或该文件的结束.
(C11§6.10.3.51; C++§16.3.5[cpp.scope]1)宏定义持续(独立于块结构),直到
#undef遇到相应的指令或(如果没有遇到)直到结束预处理翻译单元.翻译阶段4后,宏定义没有意义.
如果我们看一下这个程序:
#define NUM 10
#define FOO NUM
#undef NUM
#define NUM 20
FOO
Run Code Online (Sandbox Code Playgroud)
我们看到NUM第1行的宏定义完全持续到第3行.这些行中没有可替换的文本,所以从不使用定义; 因此,该计划实际上与以下内容相同:
#define FOO NUM
#define NUM 20
FOO
Run Code Online (Sandbox Code Playgroud)
在这个程序中,在第三行中,有用于活性定义FOO,与替换列表NUM,以及用于NUM与替换列表20.将FOO其替换为替换列表,制作它NUM,然后再次扫描宏,导致NUM替换为其替换列表20.该替换再次被重新扫描,但没有定义的宏,因此最终结果是令牌20留在翻译阶段5进行处理.
Sho*_*hoe 20
在:
FOO
Run Code Online (Sandbox Code Playgroud)
预处理器将替换它NUM,然后它将替换NUM为当前定义的,即20.
最初的四行相当于:
#define FOO NUM
#define NUM 20
Run Code Online (Sandbox Code Playgroud)
M.M*_*M.M 14
C11标准说(和其他版本的C和C++一样):
表单的预处理指令
# define identifier replacement-list new-line定义了一个类似于对象的宏,它使宏名称的每个后续实例都被构成指令其余部分的预处理标记的替换列表替换.然后重新扫描替换列表以获取更多宏名称,如下所示.
然而,它也在另一部分说(感谢rici指出这一点).
除非另有说明,否则预处理指令中的预处理标记不受宏扩展的影响.
因此,实际上不会替换在另一个#define指令中找到的宏名称的后续实例.
您的行#define FOO NUM定义了FOO以后找到令牌时(在另一个#define指令之外!),它将被令牌替换NUM.
替换令牌后,重新扫描发生,如果NUM本身是宏,则NUM在此时替换.(如果NUM扩展到包含宏,那么扩展,等等).
所以你的步骤顺序实际上是:
NUM 定义为 10FOO 定义为 NUMNUM 未定义并重新定义为 20FOO 扩展到 NUMNUM扩展到20在另一个常见的预处理器技巧中可以看到此行为,将宏的定义值转换为字符串:
#define STR(X) #X
#define STR_MACRO(X) STR(X)
#define NUM 10
puts( STR_MACRO(NUM) ); // output: 10
Run Code Online (Sandbox Code Playgroud)
如果我们写了puts( STR(NUM) )那么输出就是NUM.
输出10是可能的,因为像以前一样,第二个#define实际上并没有扩展STR.所以这段代码中的步骤顺序是:
STR(X) 定义为 #XSTR_MACRO(X) 定义为 STR(X)NUM 定义为 10STR_MACRO并且NUM都扩大了; 结果是puts( STR(10) );STR(10)扩展到"10"| 归档时间: |
|
| 查看次数: |
2866 次 |
| 最近记录: |