mat*_*att 6 c c++ stringification c-preprocessor
为什么这些代码块产生不同的结果?
一些常用代码:
#define PART1PART2 works
#define STRINGAFY0(s) #s
#define STRINGAFY1(s) STRINGAFY0(s)
Run Code Online (Sandbox Code Playgroud)
情况1:
#define GLUE(a,b,c) a##b##c
STRINGAFY1(GLUE(PART1,PART2,*))
//yields
"PART1PART2*"
Run Code Online (Sandbox Code Playgroud)
案例2:
#define GLUE(a,b) a##b##*
STRINGAFY1(GLUE(PART1,PART2))
//yields
"works*"
Run Code Online (Sandbox Code Playgroud)
案例3:
#define GLUE(a,b) a##b
STRINGAFY1(GLUE(PART1,PART2*))
//yields
"PART1PART2*"
Run Code Online (Sandbox Code Playgroud)
我正在使用VS.net 2005 sp1中的MSVC++
编辑:目前我认为预处理器在扩展宏时的工作方式如下:步骤1: - 取出正文 - 删除##运算符周围的任何空格 - 解析字符串,如果找到的标识符与名称匹配一个参数: - 如果它在##运算符旁边,用参数的文字值(即传入的字符串)替换标识符 - 如果它不在##运算符旁边,则运行整个解释过程首先是参数的值,然后用该结果替换标识符.(忽略stringafy单个'#'case atm) - 删除所有##运算符
第2步: - 获取结果字符串并解析任何宏
现在,我认为所有3个案例都应该产生完全相同的结果字符串:
PART1PART2*
因此,在第2步之后,应该导致
作品*
但至少应该导致同样的事情.
情况 1 和 2 没有定义的行为,因为您很想将 a 粘贴*到一个预处理器标记中。根据预处理器的关联规则,这要么尝试将标记粘合在一起PART1PART2(或只是PART2)并且*粘合在一起。在你的情况下,这可能会默默地失败,这是当事情未定义时可能的结果之一。PART1PART2随后的标记*将不再被考虑进行宏扩展。然后字符串化会产生您看到的结果。
我的海湾合作委员会在你的例子中表现不同:
/usr/bin/gcc -O0 -g -std=c89 -pedantic -E test-prepro.c
test-prepro.c:16:1: error: pasting "PART1PART2" and "*" does not give a valid preprocessing token
"works*"
Run Code Online (Sandbox Code Playgroud)
总结一下你的案例 1 有两个问题。
##算子的评估顺序在情况 3 中,您的编译器给出了错误的结果。它应该
STRINGAFY1GLUEGLUE结果是PART1PART2*works*STRINGAFY1