为什么注释不能被Visual C ++ 2008中的空格替换

时间:2010-12-17 10:23:41

标签: c++ comments

在Visual Studio 2008(没有SP1)中,我可以编译并运行此代码

// vcconsole.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#define NOERROR
#ifdef   /* 

   */  NOERROR
void pr() {
 printf("hello world..\n");
} 
#endif

int _tmain(int argc, _TCHAR* argv[])
{
 pr();
 return 0;
}

但是如果我用空格手动替换块注释:

// vcconsole.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#define NOERROR
#ifdef      

       NOERROR
void pr() {
 printf("hello world..\n");
} 
#endif

int _tmain(int argc, _TCHAR* argv[])
{
 pr();
 return 0;
}

无法编译错误:

1>------ Build started: Project: vcconsole, Configuration: Debug Win32 ------
1>Compiling...
1>vcconsole.cpp
1>c:\x64\winproj\vcconsole\vcconsole.cpp(6) : fatal error C1016: #if[n]def expected an identifier
1>Build log was saved at "file://c:\x64\winproj\vcconsole\Debug\BuildLog.htm"
1>vcconsole - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

为什么2不等同?

这让我很担心,因为我正在使用一个工具来删除我的c ++源代码中的所有注释(我出于其他原因需要这样做),然后再编译它们。如果2不相同,我的工具可能会失败。

4 个答案:

答案 0 :(得分:3)

标准中有一些内容,例如注释被单个空格替换......有效地删除了换行符。你的工具也应该这样做。

请注意,在[lex.parses] 2.1.1.3下,“每个注释都被一个空格字符替换。”在2.1.1.4之前执行“预处理指令并扩展宏调用。”。

正如unquiet mind观察到的那样,预处理程序指令只从介绍性预处理程序令牌延伸到下一个换行符,因此您不能将该符号放在后续行上(除非您使用反斜杠转义符在早期解析中有效地组合行相)。

所以,我对微软不兼容的预处理切换行为的初步解释是:Visual C ++在保留评论中的换行符时做了非标准的事情(可能有助于跟踪行号),因此它需要构建一些跟踪和对随后的多行预处理指令的容忍度,使它们保持工作。 / P和/ E输出非标准多行指令,但丢失了可编辑的跟踪元数据。

答案 1 :(得分:2)

用空格替换会导致:

#ifdef      NOERROR

但是,您替换为空格和换行符。预处理程序指令由换行符终止,就像C ++语句以分号结束一样。

答案 2 :(得分:2)

从标准,第16.1节

  

唯一的空白字符   应出现在一个预处理令牌之间   预处理指令(来自   在介绍#preprocessing之后   在之前的令牌   终止新行字符)   空格和水平标签(包括   已替换注释或可能包含其他空格的空格   翻译阶段的人物3)。

g ++也(正确地)无法编译代码。

答案 3 :(得分:1)

第一个有效,因为注释是注释,因此预处理器和编译器会忽略它。第二个不起作用,因为宏不能跨越多行,除非你将\作为每行的最后一个字符。

如果要自动删除注释,但要避免使用预处理器,可以尝试首先运行预处理器,然后从预处理文件中删除注释,然后编译它们。