如C99 标准中翻译阶段的复制粘贴描述中所述,删除注释(它们被单个空格替换)发生在翻译阶段 3,而预处理指令被处理,宏在阶段 4 被扩展。
在 C90 标准中(我只有硬拷贝,所以没有复制粘贴)这两个阶段以相同的顺序发生,尽管翻译阶段的描述在某些细节上与 C99 标准略有不同——事实上在处理预处理指令和扩展宏之前,注释被删除并替换为单个空格字符并没有什么不同。
同样,C++ 标准使这两个阶段以相同的顺序发生。
至于//
应该如何处理 ' ' 注释,C99 标准是这样说的(6.4.9/2):
除了在字符常量、字符串文字或注释中,字符 // 引入了一个注释,该注释包括所有多字节字符,直到但不包括下一个换行符。
C++ 标准说 (2.7):
字符 // 开始一个注释,它以下一个换行符结束。
因此,您的第一个示例显然是该翻译器的错误-扩展宏时应保留;
之后的“ ”字符-注释字符不应成为宏的“内容”的一部分。foo(a)
foo()
the foo()
但是由于您面临着一个有问题的翻译器,您可能希望将宏定义更改为:
#define foo(x) /* junk */
解决该错误。
但是(我在这里偏离了主题......),因为在处理注释之前发生了行拼接(换行之前的反斜杠),您可能会遇到类似这样的讨厌代码:
#define evil( x) printf( "hello "); // hi there, \
printf( "%s\n", x); // you!
int main( int argc, char** argv)
{
evil( "bastard");
return 0;
}
这可能会让写它的人感到惊讶。
或者更好的是,尝试以下由喜欢框式评论的人(当然不是我!)写的:
int main( int argc, char** argv)
{
//----------------/
printf( "hello "); // Hey, what the??/
printf( "%s\n", "you"); // heck?? /
//----------------/
return 0;
}
根据您的编译器是否默认处理三元组(编译器应该这样做,但由于三元组几乎让所有遇到它们的人感到惊讶,一些编译器决定默认关闭它们),您可能会或可能不会得到您想要的行为 -当然,无论是什么行为。