Chinaunix首页 | 论坛 | 博客
  • 博客访问: 450359
  • 博文数量: 88
  • 博客积分: 2677
  • 博客等级: 少校
  • 技术积分: 893
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-13 08:01
文章分类

全部博文(88)

文章存档

2017年(3)

2016年(1)

2012年(4)

2011年(4)

2010年(57)

2009年(19)

我的朋友

分类: LINUX

2010-10-07 10:40:53


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

#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语句的位置,看其被预编译替换成了什么?
这样就更好理解了。


GNU的CPP预编译器

更多用法参考:

另可参考:可变参数宏
阅读(6426) | 评论(1) | 转发(0) |
0

上一篇:反汇编工具

下一篇:*argv[] **argv 的区别

给主人留下些什么吧!~~

abin96302015-03-29 12:14:00

文章中,好像有些地方不是特别准确:
1. args...和 args,...两者是不一样的。
2. 宏定义中的 ##args的作用,不是将 args...中的参数串起来
  2.1 其中 ##符号应该是可以省略的(在某些情况下),直接使用 args也是可以达到类似效果。具体细微差别可以看下面
  2.2 通常会附加上 ##符号,是因为: 如果DBG_OUTPUT中,只有 format,而没有任何 args参数的话,宏定义中的 ” format, ##args"会变成 ”format",其中 format后的 ”,“会被取消,因此可以通过编译。如果没有 ##的话,编译是会提示错误的

以上也是看了http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html#Variadic-Macros中的说明。呵呵