3.6 Variadic Macros

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 eprintf(...) fprintf (stderr, __VA_ARGS__)

This kind of macro is called variadic. When the macro is invoked, all the tokens in its argument list after the last named argument (this macro has none), including any commas, become the variable argument. This sequence of tokens replaces the identifier __VA_ARGS__ in the macro body wherever it appears. Thus, we have this expansion:

     eprintf ("%s:%d: ", input_file, lineno)
==> fprintf (stderr, "%s:%d: ", input_file, lineno)

The variable argument is completely macro-expanded before it is inserted into the macro expansion, just like an ordinary argument. You may use the ‘#’ and ‘##’ operators to stringify the variable argument or to paste its leading or trailing token with another token. (But see below for an important special case for ‘##’.)

If your macro is complicated, you may want a more descriptive name for the variable argument than __VA_ARGS__. CPP permits this, as an extension. You may write an argument name immediately before the ‘...’; that name is used for the variable argument. The eprintf macro above could be written

     #define eprintf(args...) fprintf (stderr, args)

using this extension. You cannot use __VA_ARGS__ and this extension in the same macro.

You can have named arguments as well as variable arguments in a variadic macro. We could define eprintf like this, instead:

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

This formulation looks more descriptive, but unfortunately it is less flexible: you must now supply at least one argument after the format string. In standard C, you cannot omit the comma separating the named argument from the variable arguments. Furthermore, if you leave the variable argument empty, you will get a syntax error, because there will be an extra comma after the format string.

     eprintf("success!\n", );
==> fprintf(stderr, "success!\n", );

GNU CPP has a pair of extensions which deal with this problem. First, you are allowed to leave the variable argument out entirely:

     eprintf ("success!\n")
==> fprintf(stderr, "success!\n", );

Second, the ‘##’ token paste operator has a special meaning when placed between a comma and a variable argument. If you write

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

and the variable argument is left out when the eprintf macro is used, then the comma before the ‘##’ will be deleted. This does not happen if you pass an empty argument, nor does it happen if the token preceding ‘##’ is anything other than a comma.

     eprintf ("success!\n")
==> fprintf(stderr, "success!\n");

The above explanation is ambiguous about the case where the only macro parameter is a variable arguments parameter, as it is meaningless to try to distinguish whether no argument at all is an empty argument or a missing argument. CPP retains the comma when conforming to a specific C standard. Otherwise the comma is dropped as an extension to the standard.

The C standard mandates that the only place the identifier __VA_ARGS__ can appear is in the replacement list of a variadic macro. It may not be used as a macro name, macro argument name, or within a different type of macro. It may also be forbidden in open text; the standard is ambiguous. We recommend you avoid using it except for its defined purpose.

Variadic macros became a standard part of the C language with C99. GNU CPP previously supported them with a named variable argument (‘args...’, not ‘...’ and __VA_ARGS__), which is still supported for backward compatibility.

c语言中三个点的解释 : variadic的更多相关文章

  1. 关于C语言中整数范围的一些解释

    示例代码 #include <stdio.h> int main() { ; printf("%d\n", c); ; printf("%d\n", ...

  2. C语言中最常用的三种输入输出函数scanf()、printf()、getchar()和putchar()

    本文给大家介绍C语言中最常用的三种输入输出函数scanf().printf().getchar()和putchar(). 一.scanf()函数格式化输入函数scanf()的功能是从键盘上输入数据,该 ...

  3. C语言中的三字母词

    C语言中的三字母词(trigraph) 在ANSI C标准中,定义了9个三字母词(trigraph),三字母词就是几个字符的序列,合起来表示另一个字符.三字母词使C语言环境可以在缺少一些必需字符的字符 ...

  4. C语言中的三值合一

    在学习C语言中我们会发现这样一种情况: #include<stdio.h> Int main() { Int ar[10]; printf(“%p\n”,ar); printf(“%p\n ...

  5. C语言中可变参数的函数(三个点,“...”)

    C语言中可变参数的函数(三个点,“...”) 本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end ...

  6. c语言中字符串数组初始化的一点总结&& c++访问控制的三种方式

    char *c[]={"ONE","TWO","THREE","FOUR"}; // c语言中定义了一个字符串数组(也称 ...

  7. 【】VMware vSphere中三种磁盘规格的解释说明

    在VMware vSphere中,不管是以前的5.1版本,或者是现在的6.5版本,创建虚拟机时,在创建磁盘时,都会让选择磁盘的置备类型,如下图所示,分为: 厚置备延迟置零 厚置备置零 Thin Pro ...

  8. C语言中的栈和堆

    原文出处<http://blog.csdn.net/xiayufeng520/article/details/45956305#t0> 栈内存由编译器分配和释放,堆内存由程序分配和释放. ...

  9. C语言中的强符号与弱符号

    转自:http://blog.csdn.net/astrotycoon/article/details/8008629 一.概述 在C语言中,函数和初始化的全局变量(包括显示初始化为0)是强符号,未初 ...

随机推荐

  1. openssl生成ssl证书

    openssl生成ssl证书 x509证书一般会用到三类文,key,csr,crt. Key 是私用密钥openssl格,通常是rsa算法. Csr 是证书请求文件,用于申请证书.在制作csr文件的时 ...

  2. 没想到cnblog也有月经贴,其实C#值不值钱不重要。

    呵呵,就不倚老卖老了,从basic走过来,一路经历vb,vf,delphi,C#,php,asp,html,js,css,太多太多的开发语言,包括面向对象编程思想,语义化页面结构等等,除了高级的编程技 ...

  3. JNI开发中String转换chat*工具

    char* Jstring2CStr(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = env->FindCla ...

  4. 对restful的理解

    最近在学习web api,从而涉及到了restful风格,我的理解是restful风格,每个链接都会对资源进行相应的操作(CRUD),如果一个链接不包含资源,则可能不符合restful风格,借此想请教 ...

  5. KindEditor 编辑器使用方法

    http://kindeditor.net/docs/usage.html 编辑器使用方法 1. 下载编辑器 下载 KindEditor 最新版本,下载之后打开 examples/index.html ...

  6. 古诗词api,诗词接口,诗词api,中国诗词

    服务商:api.getlove.cn 分类:诗词 更新时间:2016-03 如果接口不满足您的要求,您可以联系qq:2265658022购买完整的数据库 免费apikey:56eab527a0facb ...

  7. LR12.53—第3课:重播Vuser脚本

    第3课:重播Vuser脚本 在前面的教训,你记录了一组典型的用户行为,并准备重播脚本. 重播脚本之前,您可以配置脚本的运行时设置,它定义了Vuser的行为. 注:记录与基于Web的协议的地方WebTo ...

  8. ps基础知识

    一 1. ps常用快捷键:ctrl+d 结束选区    ctrl+alt+z  返回          ctrl+z 撤销           ctrl+x 剪切 ctrl+t 编辑图片    ctr ...

  9. Ax 导出EXCEL给范围内的每个单元格加边框

    1. 首先在Class\SysExcelRange加画边框的方法 思路用EXCEL录宏的功能得到给一批单元格画格子的VBA代码,在AX将对象转为COM对象,基本VBA代码也能装为AX内能用的内容. p ...

  10. cs11_adventure c++_lab1

    exercise1.cc #include <iostream> #include <vector> #include <stdlib.h> #include &l ...