GNU C语言 宏定义 #args ##args

来源:互联网 发布:微信斗图软件 编辑:程序博客网 时间:2024/06/09 19:43

文章转自:http://blog.chinaunix.net/uid-21830881-id-1813972.html

如果大家看到,下记代码,一些人一定会有一些疑问

#define DBG_OUTPUT(fmt, args...) printf("CK File[%s:%s(%d)]:" fmt "\n", __FILE__,__FUNCTION__, __LINE__, ##args)


args...是什么?
##args 是什么?
如何应用?
如何传递?
..........


①args...

GCC编译器中的CPP预编译器,是支持这种写法的,args... 比 args,... 的写法可读性较好。

含义:应该是DBG_OUTPUT的参数,第一个传给fmt, 第二个开始传给args...可为多个。

②##args
 ##args的意思,就是把args...中的多个参数,串连起来。
 
另外,如果写成 #fmt的话,就是把fmt传进来的内容以字符串形式输出。(下面例子中会说明)



例代码①

#include <stdio.h>


#define DBG_OUTPUT(fmt,args...) printf("CK File[%s:%s(%d)]:" fmt "\n", __FILE__,__FUNCTION__, __LINE__, ##args)

int
main(int argc,char **argv){

    char                j;
    unsigned char        k;

    j = 0xF1;
    k = 0xF1;

    DBG_OUTPUT("j[%d]k[%d]", j, k);
    /* printf("CK File[%s:%s(%d)]:" "j[%d]k[%d]" "\n", __FILE__, __FUNCTION__, __LINE__, j, k) */
    return 0;
}
/* test.c */


可以看出来么?
DBG_OUTPUT("j[%d]k[%d]", j, k); 预编译后实际内容就是其下行的注释中的内容。

"j[%d]k[%d]"作为一个参数,传递给了fmt。(包含 ""双引号)
j, k作为两个参数传给args... , 在printf语句中,使用的是##args,所以这两个参数,被串联放在了printf语句中。

下面说明#fmt(就是一个#符号是什么意思)

#include <stdio.h>


#define DBG_OUTPUT(fmt,args...) printf("CK File[%s:%s(%d)]:" #fmt "\n", __FILE__,__FUNCTION__, __LINE__, ##args)

int
main(int argc,char **argv){

    char                j;
    unsigned char        k;

    j = 0xF1;
    k = 0xF1;

    DBG_OUTPUT(j[%d]k[%d], j, k);
    /* printf("CK File[%s:%s(%d)]:" "j[%d]k[%d]" "\n", __FILE__, __FUNCTION__, __LINE__, j, k) */
    return 0;
}
/* test.c */


与前一例代码有 2 点不同。
①DBG_OUTPUT的宏定义的printf语句中,将fmt换成了#fmt
②main()函数中的DBG_OUTPUT的语句中,""双引号,去掉了。

也就是说,j[%d]k[%d]作为一个参数传递给了fmt,在printf中使用的是#fmt,所以j[%d]k[%d]作为字符串输出,相当于"j[%d]k[%d]"。

所以,两段例代码的注释部分是完全一样的。输出结果当然也一样。



注:
GCC的option -E 为向标准输入输出中,输出预编译结果。
所以,通过命令
$ gcc -E test.c >& test.i
(生成预编译结果,保存在test.i的文本文件中)
再打开,test.i文件,在最下面找到原DBG_OUTPUT语句的位置,看其被预编译替换成了什么?
这样就更好理解了。