##宏

来源:互联网 发布:mysql入门经典 王雨竹 编辑:程序博客网 时间:2024/05/02 02:20

注:原文由Pthread发表于西安交通大学兵马俑BBS,转载请保留此信息。

http://bbs.xjtu.edu.cn/BMYHZGNLVSWCXFTOHGOWXNNLMEHACNIBZUPM_I/con?B=C_Cpp&F=M.1208265882.A&N=6510&T=-3793

http://bbs.xjtu.edu.cn/BMYHZGNLVSWCXFTOHGOWXNNLMEHACNIBZUPM_I/con?B=C_Cpp&F=M.1208272831.A&N=6524&T=0

 

发信人: shaofeng (恨关羽不能张飞喜八戒终得悟空), 信区: C_Cpp

标题: 请教这几种宏定义区别

发信站: 兵马俑BBS (Tue Apr 15 17:35:26 2008), 本站(bbs.xjtu.edu.cn)

 

#define __D(fmt, args...) fprintf(stdout, "Debug: " fmt, ## args)

#define __E(fmt) fprintf(stderr, "Debug: " fmt)

#define __C(fmt, args...) fprintf(stdout, "Debug: " fmt,args)

 

 

发信人: pthread (ZZ), 信区: C_Cpp

标题: Re: 请教这几种宏定义区别

发信站: 兵马俑BBS (Tue Apr 15 21:24:42 2008), 本站(bbs.xjtu.edu.cn)

 

是这样的

1. stdout, stderr //这个就不说了吧

2. 参数个数不同

3. ## 连接符可以在预编译的时候去掉前面的逗号

说仔细点应该是: "##"出现在逗号和变量参数之间时,如果变量整个被忽略的时候,##前面的逗号会被去掉,但是变量不能为空,也就是说__D(fmt,) __C(fmt,)都是不允许的。__C(fmt)不行,而__D(fmt)则是可以的。

 

看两个例子就知道怎么用的了:

1.

#include <stdio.h>

 

#define __D(fmt, args...) fprintf(stdout, "Debug: " fmt, ## args)

#define __E(fmt) fprintf(stderr, "Debug: " fmt)

#define __C(fmt, args...) fprintf(stdout, "Debug: " fmt,args)

 

int main(){

    __E("A vital error occurred./n");

    __C("A vital error occurred at %s : %d./n",__FILE__,__LINE__);

    __D("A vital error occurred at %s : %d./n",__FILE__,__LINE__);

    return 0;

}

 

输出为:

Debug: A vital error occurred.

Debug: A vital error occurred at test.c : 9.

Debug: A vital error occurred at test.c : 10.

 

gcc -o test.i -E test.c,打开test.i查看预处理(宏展开)结果

int main(){

    fprintf(stderr, "Debug: " "A vital error occurred/n");

    fprintf(stdout, "Debug: " "A vital error occurred at %s, %d/n","main.c",9);

    fprintf(stdout, "Debug: " "A vital error occurred at %s, %d/n","main.c",10);

    return 0;

}

 

E CD的区别清楚了吧,这里C,D看来是一样的。

 

再看一个例子:

*****************************************************************

2.

#include <stdio.h>

 

#define __D(fmt, args...) fprintf(stdout, "Debug: " fmt, ## args)

#define __E(fmt) fprintf(stderr, "Debug: " fmt)

#define __C(fmt, args...) fprintf(stdout, "Debug: " fmt,args)

 

int main(){

    __E("A vital error occurred./n");

    __C("A vital error occurred./n");

    __D("A vital error occurred./n");

    return 0;

}

 

此时编译不过,问题在__C。还是用gcc -o test.i -E test.c,得到预处理结果

int main(){

    fprintf(stderr, "Debug: " "A vital error occurred./n");

    fprintf(stdout, "Debug: " "A vital error occurred./n",); //注意这里的逗号

    fprintf(stdout, "Debug: " "A vital error occurred./n");

    return 0;

}

 

所以在参数为空的时候,__C编译失败,__D通过。

明白CD的区别了吧。

 

 

补充两句:

 

1. 关于参数省略和参数为空

对于#define __D(fmt, args...) fprintf(stdout, "Debug: " fmt, ## args)

__D(fmt)是参数省略, gcc会去掉##前面的逗号,编译通过

__D(fmt , )是参数为空,##前面的逗号不会被去掉,编译错误

 

2.  gcc __D(fmt)的处理(去掉前面的逗号)是符合c99标准的。但是如果有下面的例子(虽然程序本身没什么意义)

#include <stdio.h>

#define __D(args...) fprintf(stdout, "DEBUG: %s/n", ##args)

 

int main(){

    __D();

    return 0;

}

 

__D() 没有参数,所以既可以理解为参数省略,也可以理解为参数为空,按c99的标准这种情况下,逗号应该保留。然而gcc默认会去掉逗号。

gcc test.c -o test          //通过

gcc test.c -o test -std=c99 //c99标准,编译错误, fprintf(stdout, "DEBUG: %s/n",);

原创粉丝点击