C语言的编译期行为(三) #的妙用

来源:互联网 发布:寻仙udp的3100端口 编辑:程序博客网 时间:2024/04/30 04:12

在C语言中,所有以#开头的行被认为是需要预处理器处理的“预处理器指令”。#include、#define等常见的用法不再赘诉,可以参考任何一本C语言的书籍。这里仍然讲一些需要注意的用法。下面的代码主要说明#出现在宏定义内部作为“字符串化”操作符的用法,另外附带介绍一些特别的习惯和用法。

#include <stdio.h># //此行只包含一个#,被当作空行处理#define PRINT_ADD(a, b)                               \    do                                                \    {                                                 \        char fmt[] = "%s + %s = %d\n";                \        printf(fmt, #a, #b, ((a)+(b)));               \    } while (0)                                       \int main(int argc, char** argv){    int var_a = 6;    int var_b = 9;    PRINT_ADD(3, 5);    PRINT_ADD(var_a, var_b);    PRINT_ADD(var_a * 2 , var_b);    return 0;}

只包含一个#的行会被如何处理?

第3行:只包含一个#的行被标准C语言认为是空行,#会被预处理器用空行替换掉。

宏函数定义为什么要使用do while循环的格式书写?

第5行到第10行定义了一个宏函数PRINT_ADD(a, b)。

1. 在宏函数中我们希望能够定义局部变量,但是C99以前的标准C语言要求所有变量必须一个作用域开始处定义。而宏展开后即变成了普通的代码行,并不能保证满足满足这一点的要求,所以宏函数需要采用大括号的形式。

2. 我们希望在程序中尽量像调用普通函数那样使用宏函数,即要求其后有一个分号作为结尾。使用这种形式有效地要求了用户必须使用分号。

3. 编译器随后的处理中,会有效地优化掉这种注定只执行一次的循环语句。所以一般来说不会影响性能。

第9行中#的作用是什么?

#出现在宏定义内部被认为是“字符串化”操作符。它的作用是将传入的参数整体宏替换为相对应的字符串。

例如:

第17行传入的3和5: #a被替换为"3",#b被替换为"5", a被替换为3, b被替换为5

第18行传入的var_a和var_b: #a被替换为"var_a",#b被替换为"var_a", a被替换为var_a, b被替换为var_b

第19行传入的var_a * 2和var_b: #a被替换为"var_a * 2",#b被替换为"var_a", a被替换为var_a * 2, b被替换为var_b

所以,程序运行的结果为:

3 + 5 = 8

var_a + var_b = 15

var_a * 2 + var_b = 21


P.S.:以下是VS2008预处理器处理后输出的代码:

int main(int argc, char** argv){    int var_a = 6;    int var_b = 9;    do { char fmt[] = "%s + %s = %d\n"; printf(fmt, "3", "5", ((3)+(5))); } while (0);    do { char fmt[] = "%s + %s = %d\n"; printf(fmt, "var_a", "var_b", ((var_a)+(var_b))); } while (0);    do { char fmt[] = "%s + %s = %d\n"; printf(fmt, "var_a * 2", "var_b", ((var_a * 2)+(var_b))); } while (0);    return 0;}



(■版权声明: 原创内容,转载仅限非商业用途,并需注明出处: http://blog.csdn.net/LoveASPDotNet)




原创粉丝点击