这里有一个相关的例子。它显然不是有效的C,但我只是在这里处理预处理器,所以代码实际上不需要编译。
#define IDENTITY(x) x
#define PREPEND_ASTERISK(x) *x
#define PREPEND_SLASH(x) /x
IDENTITY(literal)
PREPEND_ASTERISK(literal)
PREPEND_SLASH(literal)
IDENTITY(*pointer)
PREPEND_ASTERISK(*pointer)
PREPEND_SLASH(*pointer)
运行gcc的预处理器:
gcc -std=c99 -E macrotest.c
这将产生:
(...)
literal
*literal
/literal
*pointer
**pointer
/ *pointer
请注意最后一行的多余空格。
这看起来像是一个防止宏扩展到“/*”的特性,我相信这是出于善意。但乍一看,我在C99标准中找不到任何与这种行为相关的东西。再说一次,我在C没有经验。有人能解释一下吗?这是哪里规定的?我想,一个遵循C99的编译器不应该仅仅因为可能会防止编程错误而在宏扩展期间插入额外的空格。
最佳答案
源代码在被cpp处理之前已经被标记化了。
因此,您所拥有的是一个/
和一个*
令牌,它不会隐式地组合到一个/*
“令牌”(因为/*并不是我放入的预处理器令牌)。
如果使用-e输出预处理的源cpp,则需要插入一个空格,以避免后续编译器进程读取/*
。
相同的功能防止两个不同宏的符号在输出时组合成一个标记。
真正将两个预处理器标记粘贴在一起的唯一方法是使用运算符:
#define P(x,y) x##y
...
P(foo,bar)
结果标记
+
P(+,+)
导致令牌
++
,但是P(/,*)
无效,因为
foobar
不是有效的预处理器标记。关于c - 在C宏扩展过程中,是否存在将宏扩展为“/*”的特殊情况?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4165278/