##宏
来源:互联网 发布:mysql入门经典 王雨竹 编辑:程序博客网 时间:2024/05/02 02:20
注:原文由Pthread发表于西安交通大学兵马俑BBS,转载请保留此信息。
发信人: 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 与C,D的区别清楚了吧,这里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通过。
明白C和D的区别了吧。
补充两句:
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",);