如此处复制粘贴的C99标准翻译阶段描述所述,消除注释(它们被替换为单个空格)发生在第3个翻译阶段,而预处理指令在第4个阶段处理和宏扩展。
在C90标准中(我只有纸质版,因此无法复制粘贴),这两个阶段按相同顺序发生,尽管翻译阶段的描述在某些细节上与C99标准略有不同-注释被删除并替换为单个空格字符,然后再处理预处理指令和宏扩展。
同样,C++标准将这2个阶段按相同顺序发生。
至于如何处理'//
'注释,C99标准如下(6.4.9/2):
除了在字符常量、字符串文字或注释内部外,字符//引入一个注释,其中包括所有多字节字符,但不包括下一个新行字符。
C++标准如下(2.7):
字符//开始一个注释,该注释以下一个新行字符结束。
所以你的第一个例子显然是该翻译者的错误 - 在展开
foo()
宏时,应该保留
foo(a)
后面的'
;
'字符 - 注释字符不应成为
the foo()
宏的“内容”的一部分。
但是,由于你面对的是有缺陷的翻译器,你可能需要更改宏定义为:
#define foo(x)
为了解决这个 bug,可以采用以下方法。
然而(我有些跑题了……),由于行拼接(即在换行符前加上反斜杠)会在注释处理之前进行,你可能会遇到以下这段不好的代码:
#define evil( x) printf( "hello ");
int main( int argc, char** argv)
{
evil( "bastard");
return 0;
}
这可能会让写这段代码的人感到惊讶。
或者更好的方法是尝试下面这个,由某个喜欢盒式注释的人(肯定不是我!)编写:
int main( int argc, char** argv)
{
printf( "hello ");
printf( "%s\n", "you");
return 0;
}
根据您的编译器默认是否处理三字符序列(编译器应该处理,但由于三字符序列会让几乎所有遇到它们的人感到惊讶,因此一些编译器决定默认关闭它们),您可能会得到或者不会得到所需的行为 - 当然,无论那种行为是什么。
//
注释,但编译器理解吗?请记住,最初 C 只能理解/* */
注释,而//
是 C++ 的扩展。我认为 C 只在 C99 中引入了//
。 (我的历史记忆是否正确?)实际上,无论您使用哪个编译器,我都很想看看它如何处理/*
。 - Aaron McDaid