开发者

Why Comment Cannot be Replaced by Spaces in Visual C++ 2008

In Visual Studio 2008 (without SP1), I can compile and run this code

// 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;
}

But if I manually replace the block comment with spaces :

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

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

       NOER开发者_开发问答ROR
void pr() {
 printf("hello world..\n");
} 
#endif

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

it fails to compile with error:

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 ==========

Why the 2 are not equivalent?

This concerns me because I am using a tool to remove all comments from my c++ source code (I need to do this for other reasons) before compiling them. If the 2 are not equivalent somehow, my tool may fail.


There's something in the Standard like a comment is replaced by a single space... that effectively removes the newlines. Your tool should do the same.

Note that under [lex.parses] 2.1.1.3 "Each comment is replaced by one space character." before 2.1.1.4 "Preprocessing directives are executed and macro invocations are expanded.".

As unquiet mind observes, a preprocessor directive only extends from the introductory preprocessor token through to the next newline, so you can't put the symbol on a subsequent line (unless you use backslash escapes to effectively combine lines in an early parsing phase).

So, my tentative explanation for Microsoft's non-compliant preprocessing switch behaviour is: Visual C++ is doing something non-Standard in preserving newlines in comments (probably to help track line numbers), so it then needs to build in some tracking and tolerance for the consequent multi-line preprocessing directives, keeping them working. /P and /E output the non-Standard multi-line directives, but lose that tracking metadata that makes it compilable.


Replacing by a space would result in:

#ifdef      NOERROR

However, you replaced by spaces and newlines. Preprocessor directives are terminated by newlines just like C++ statements are terminated by semicolons.


From the Standard, section 16.1

The only white-space characters that shall appear between preprocessing tokens within a
preprocessing directive (from just after the introducing #preprocessing token through just before the terminating new-line character) are space and horizontal-tab (including spaces that have replaced comments or possibly other white-space characters in translation phase 3).

g++ also (correctly) fails to compile the code.


The first one works, because a comment is a comment, and hence ignored by the preprocessor and the compiler. The second one does not work, because macros cannot span multiple lines, unless you put a \ as the last character of each line.

If you want to automatically remove comments, but avoid trouble with the preprocessor, what you could try is to run the preprocessor first, then remove comments from the preprocessed files, and then compile those.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜