请有人对我自己的问题的答案投票。
感谢Martin York 的 想法,我发现在 Visual Studio 中,解决方案看起来非常简单(有待进一步测试)。只需将所有预处理器指令重命名为其他内容(可以使用无效的 c++ 语法)并将 cl.exe 与 /P
一起使用
cl target.cpp /P
它会产生一个target.i。它包含源减去 cmets。只需将以前的指令重命名回来即可。可能您需要删除 cl.exe 生成的 #line 指令。
这是可行的,因为根据 MSDN,翻译的阶段是这样的:
字符映射
源文件中的字符映射到内部源表示。在这个阶段,三字母序列被转换为单字符的内部表示。
线拼接
所有以反斜杠 () 结尾并紧跟换行符的行都与源文件中的下一行连接起来,形成物理行的逻辑行。除非它为空,否则源文件必须以不带反斜杠的换行符结尾。
标记化
源文件分为预处理标记和空白字符。源文件中的注释分别替换为一个空格字符。保留换行符。
预处理
执行预处理指令并将宏扩展到源文件中。 #include 语句从任何包含文本的前三个翻译步骤开始调用翻译。
字符集映射
所有源字符集成员和转义序列都被转换为它们在执行字符集中的等价物。对于 Microsoft C 和 C++,源字符集和执行字符集都是 ASCII。
字符串连接
所有相邻的字符串和宽字符串文字都被连接起来。例如,“String”、“concatenation”变成“String concatenation”。
翻译
所有标记都经过语法和语义分析;这些标记被转换成目标代码。
联动
解析所有外部引用以创建可执行程序或动态链接库
在预处理阶段之前的标记化期间删除评论。所以只要确保在预处理阶段,没有可用的
用于处理(删除所有指令),其输出应该只是前三个阶段处理的那些。
对于用户定义的 .h 文件,使用 /FI 选项手动包含它们。生成的 .i 文件将是 .cpp 和 .h 的组合。没有 cmets。每个片段前面都有一个带有正确文件名的#line。因此,编辑器很容易将它们分开。如果我们不想手动拆分它们,可能我们需要使用某些编辑器的宏/脚本工具来自动完成。
所以,现在,我们不必关心任何预处理器指令。更好的是处理了续行字符(反斜杠)。
例如
// vc8.cpp : Defines the entry point for the console application.
//
-#include "stdafx.h"
-#include <windows.h>
-#define NOERR
-#ifdef NOERR
/* comment here */
whatever error line is ok
-#else
some error line if NOERR not defined
// comment here
-#endif
void pr() ;
int _tmain(int argc, _TCHAR* argv[])
{
pr();
return 0;
}
/*comment*/
void pr() {
printf(" /* "); /* comment inside string " */
// comment terminated by \
continue a comment line
printf(" "); /** " " string inside comment */
printf/* this is valid comment within line continuation */\
("some weird lines \
with line continuation");
}
在cl.exe vc8.cpp /P之后,它变成了这个,然后可以在恢复指令(并删除#line)后再次提供给cl.exe
#line 1 "vc8.cpp"
-#include "stdafx.h"
-#include <windows.h>
-#define NOERR
-#ifdef NOERR
whatever error line is ok
-#else
some error line if NOERR not defined
-#endif
void pr() ;
int _tmain(int argc, _TCHAR* argv[])
{
pr();
return 0;
}
void pr() {
printf(" /* ");
printf(" ");
printf\
("some weird lines \
with line continuation");
}