可变参数的宏里的‘##’操作说明(Macros with a Variable Number of Arguments)

翻译 2006年06月03日 17:16:00

摘要:

在一些论坛上看了一下有关这方面的争议,决定给大家一个“正规”的说法,防止被误导,可以对照着英文原文阅读我的翻译。

---------------------------------------------------------------------------------------------------------------------
声明:
       此文为原创翻译,欢迎转载,转载请保留如下信息
       作者:聂飞(afreez)
       联系方式:afreez@sina.com (欢迎与作者交流)
       初次发布时间:2006-06-03
      不经本人同意,不得用语商业或赢利性质目的,否则,作者有权追究相关责任!
---------------------------------------------------------------------------------------------------------------
带有可变参数的宏(Macros with a Variable Number of Arguments

1999年版本的ISO C 标准中,宏可以象函数一样,定义时可以带有可变参数。宏的语法和函数的语法类似。下面有个例子:

#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)

这里,‘’指可变参数。这类宏在被调用时,它(这里指‘’)被表示成零个或多个符号,包括里面的逗号,一直到到右括弧结束为止。当被调用时,在宏体(macro body)中,那些符号序列集合将代替里面的__VA_ARGS__标识符。更多的信息可以参考CPP手册。

GCC始终支持复杂的宏,它使用一种不同的语法从而可以使你可以给可变参数一个名字,如同其它参数一样。例如下面的例子:

#define debug(format, args...) fprintf (stderr, format, args)

这和上面举的那个ISO C定义的宏例子是完全一样的,但是这么写可读性更强并且更容易进行描述。

GNU CPP还有两种更复杂的宏扩展,支持上面两种格式的定义格式。

在标准C里,你不能省略可变参数,但是你却可以给它传递一个空的参数。例如,下面的宏调用在ISO C里是非法的,因为字符串后面没有逗号:

debug ("A message")

GNU CPP在这种情况下可以让你完全的忽略可变参数。在上面的例子中,编译器仍然会有问题(complain),因为宏展开后,里面的字符串后面会有个多余的逗号。

为了解决这个问题,CPP使用一个特殊的‘##’操作。书写格式为:

#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)

这里,如果可变参数被忽略或为空,‘##’操作将使预处理器(preprocessor)去除掉它前面的那个逗号。如果你在宏调用时,确实提供了一些可变参数,GNU CPP也会工作正常,它会把这些可变参数放到逗号的后面。象其它的pasted macro参数一样,这些参数不是宏的扩展。


GCC4.1.1.pdf 236页

5.14 Macros with a Variable Number of Arguments.

In the ISO C standard of 1999, a macro can be declared to accept a variable number of

arguments much as a function can. The syntax for defining the macro is similar to that of

a function. Here is an example:

#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)

Here ‘...’ is a variable argument. In the invocation of such a macro, it represents the

zero or more tokens until the closing parenthesis that ends the invocation, including any

commas. This set of tokens replaces the identifier __VA_ARGS__ in the macro body wherever

it appears. See the CPP manual for more information.

GCC has long supported variadic macros, and used a different syntax that allowed you

to give a name to the variable arguments just like any other argument. Here is an example:

#define debug(format, args...) fprintf (stderr, format, args)

This is in all ways equivalent to the ISO C example above, but arguably more readable

and descriptive.

GNU CPP has two further variadic macro extensions, and permits them to be used with

either of the above forms of macro definition.

In standard C, you are not allowed to leave the variable argument out entirely; but you

are allowed to pass an empty argument. For example, this invocation is invalid in ISO C,

because there is no comma after the string:

debug ("A message")

GNU CPP permits you to completely omit the variable arguments in this way. In the

above examples, the compiler would complain, though since the expansion of the macro still

has the extra comma after the format string.

To help solve this problem, CPP behaves specially for variable arguments used with the

token paste operator, ‘##’. If instead you write

#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)

and if the variable arguments are omitted or empty, the ‘##’ operator causes the preprocessor

to remove the comma before it. If you do provide some variable arguments in

your macro invocation, GNU CPP does not complain about the paste operation and instead

places the variable arguments after the comma. Just like any other pasted macro argument,

these arguments are not macro expanded.

VS2010编写自定义宏

这里所说的宏可不是指#define PI 3.14159之类的,而是按下Alt + 1,Alt + 2之类的键盘组合之后可以方便地插入一大串自定义的内容,如: /******************...
  • ajioy
  • ajioy
  • 2013年01月08日 22:38
  • 9262

redis数据库基础之基本操作

redis数据库基础之基本操作 1,简介: redis,k-v数据库,可以包含的数据类型有字符串,哈希,链表,集合,有序集合。 数据类型支持push/pop,add/remove,取交集,并...
  • SiuKong_Ngau
  • SiuKong_Ngau
  • 2017年03月23日 21:30
  • 871

rpm 宏定义(macros.in)

宏定义文件:跟宏定义相关的文件可分为两类:直接定义类 /usr/lib/rpm/macros、/usr/lib/rpm/macros.d、/usr/lib/rpm/redhat/macros、/e...
  • hawkerou
  • hawkerou
  • 2016年11月28日 16:31
  • 558

vs2005如何使用用户自定义宏(User Macros)

转:http://blog.csdn.net/loleeve/article/details/2910270
  • zhangmiaoping23
  • zhangmiaoping23
  • 2014年07月30日 11:40
  • 1692

在Ubuntu上搭建redis服务器

Redis是一个key-value存储系统。和Memcached类似,但是解决了断电后数据完全丢失的情况,而且她支持更多无化的value类型,除了和string外,还支持lists(链表)、sets(...
  • u014374031
  • u014374031
  • 2017年01月17日 21:19
  • 2478

redis操作实战

1.hash 127.0.0.1:6379> keys *ServiceConfig* 1) "NGMA_SYSTEM:com.polycom.rpum.core.dal.memi.NgmaServi...
  • hanruikai
  • hanruikai
  • 2015年06月11日 17:10
  • 787

PReprocessor Macros : 全局宏命令的应用

全局宏命令的应用应用场景:1、根据是真机还是模拟器来指定宏的不同定义;2、设置不同的宏,实现不同Target版本的判断。...
  • Aaidong
  • Aaidong
  • 2016年12月01日 20:34
  • 1778

深入理解UE4宏定义—— GENERATED_BODY

本文章由cartzhang编写,转载请注明出处。 所有权利保留。 文章链接: 作者:cartzhang一、GENERATED_BODY 都实现了什么? 在前几年的写引擎的时候,也类似使用过这些...
  • cartzhang
  • cartzhang
  • 2017年06月01日 18:37
  • 2355

cocos lua遇到的一些问题

做完lua版棋牌游戏,下面把我遇到的一些问题记录下。 一、确定版本 关于版本问题真的要好好计划下,目前苹果官方下达通牒,所有app必须支持IPv6。而lua热更新机制是去请求网站,低版本可能不支持IP...
  • msdb198901
  • msdb198901
  • 2016年08月05日 14:12
  • 2921

Redis 五种数据结构

巴拉巴拉啦 更新中.....
  • Josn_Hao
  • Josn_Hao
  • 2017年06月01日 00:30
  • 223
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:可变参数的宏里的‘##’操作说明(Macros with a Variable Number of Arguments)
举报原因:
原因补充:

(最多只允许输入30个字)