您的位置:首页 > 其它

有关宏的使用总结 - 1 (VS编译器)

2010-11-19 13:08 330 查看
11月9日

有关宏的使用总结 - 1 (VS编译器)

今天下午被宏折腾了好久,是时候,该好好总结一下有关于宏的使用了。

1.宏的分段式定义一定要注意,不能在 / 后面有任何的字符,包括空格
例如:
#define PRINTF(s) /
printf(s##"/n");
如果 #define PRINTF(s) / 这句的后面还有多余的空格,那么vc编译器将提示
error C2017: 非法的转义序列
error C2014: 预处理器命令必须作为第一个非空白空间启动

2.宏的#ifdef #endif格式的定义中,一定要注意#else或#endif之前的那句宏定义,不能加 "/"
例如:
#ifdef _DEBUG
#define PRINTF(s) /
if (s) /
printf(s##"/n"); => 注意这里绝对不能加 "/"
#else
#define PRINTF(s) /
printf(s##"/n"); => 同样这里也绝对不能加 "/"
#endif
如果此两处中任意一处加上了"/",编译将失败,编译器提示
error C1070: 文件中的 #if/#endif 对不匹配
error C2162: 应输入宏形参

3.宏的一个连接多个字符的用法
例如:
#define _STR(x) _VAL(x)
#define _VAL(x) #x
#define PRINTF(s) /
if (s) /
printf(s); /
void _tmain(int argc, _TCHAR* argv[])
{
//_ASSERTE(0);
PRINTF(__FILE__ " - " _STR(__LINE__));
}
将 __FILE__ 和 __LINE__传递给一个str来输出

4. 编译时检查宏开关
#ifdef _X86
#Pragma message(“_X86 macro activated!”)
#endif

5.当在宏里面使用临时变量定义,或者使用代码块的时候要注意使用区间包含
例如:
#define PRINTF(s) /
if (strchr(s,'F')) /
printf(s##"/n"); /
void _tmain(int argc, _TCHAR* argv[])
{
int i = 1;
if (i)
PRINTF("TRUE")
else
PRINTF("FALSE")
system("pause");
}
从上面这段代码的结果,可以看出,逻辑是完全错误的!
遇到这种情况,请使用{},或者do{}while(0);来定义局部区间
例如
#define PRINTF(s) /
{ /
if (strchr(s,'F')) /
printf(s##"/n"); /
} /
这样定义就没有问题了。

6.调试复杂的宏块最好的办法,就是直接查看输出的预编译文件,在vc下就是 /P 编译开关,MSDN相关解释如下:
项预处理 C 和 C++ 源文件并将预处理输出写入文件。此文件具有与源文件相同的基名称和 .i 扩展名。在此过程中,执行所有的预处理器指令,执行宏展开,并移除注释。若要将注释保留在预处理输出中,请将 /C 选项与 /P 一起使用。

/P 将 #line 指令添加到输出中,添加的位置是每个包含文件的开头和结尾以及被条件编译预处理器指令移除的行的周围。这些指令将预处理文件中的行重新编号。因此,在处理后期生成的错误引用原始源文件的行号而不是预处理文件中的行的行号。若要取消生成 #line 指令,请使用 /EP 和 /P。

/P 选项取消编译。它不产生 .obj 文件,即使使用 /Fo 也是如此。必须重新提交预处理文件以进行编译。/P 还取消 /FA/Fa/Fm 选项的输出文件。

在 Visual Studio 开发环境中设置此编译器选项

打开此项目的“属性页”对话框。有关详细信息,请参见设置 Visual C++ 项目属性

单击“C/C++”文件夹。

单击“预处理器”属性页。

修改“生成预处理文件”属性。

以编程方式设置此编译器选项

请参见 GeneratePreprocessedFile 属性。

示例

下列命令行预处理
ADD.C
,保留注释,添加 #line 指令,并将结果写入文件
ADD.I


CL /P /C ADD.C

请参见
编译器选项 | 设置编译器选项

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: