- 浏览: 268159 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (263)
- mysql (5)
- boost (6)
- 工具 (10)
- IT生活 (7)
- 多线程 (3)
- Ruby (15)
- php (2)
- MongoDB (39)
- 移动互联网 (2)
- 测试 (8)
- c++ (28)
- 书 (1)
- 网站 (3)
- 网络编程 (14)
- 开源软件 (1)
- 分布式计算 (1)
- 得得得 (1)
- php,wordpress (1)
- error (5)
- 编译 (2)
- 学习 (1)
- 杀毒软件 (1)
- dd (0)
- linux (21)
- 数据库 (1)
- STL (1)
- c++/c (5)
- 软件设计 (1)
- 操作系统 (4)
- 库 (2)
- win32 (1)
- s (0)
- openssl (1)
- perl (2)
- debug (1)
- windows (4)
- python (12)
- windows 防火墙 (1)
- vs (1)
- vim (2)
- vc (1)
- 浏览器插件的危害 (1)
- curl (0)
- 判断手机号码合法性的库 (0)
- 地址备注 (0)
- 安装 File::Slurp (1)
- cenos (2)
- shell (1)
- linunx (1)
- internet (1)
- software (1)
- widows (1)
- linux io (1)
- nginx (2)
- 算法 (2)
- google (1)
- protobuf (2)
- tengine (1)
- tools (1)
- lua (2)
- liunx (1)
- vcard (1)
- lua-iconv (1)
- 网络 (2)
- teat (0)
- ldconfig linux (0)
- awk (0)
- grep (0)
- windws (2)
- linux 命令 (1)
- tcp dump (1)
- vmware (1)
- question2answer (2)
- mongdb (1)
- 正则 (1)
- OCR (2)
- Windows Server (1)
最新评论
转自: http://blog.sina.com.cn/s/blog_661314940100qmfg.html
在 GNU C 中,宏可以接受可变数目的参数,就象函数一样,例如:
#define pr_debug(fmt,arg...) \
printk(KERN_DEBUG fmt,##arg)
用可变参数宏(variadic macros)传递可变参数表
你可能很熟悉在函数中使用可变参数表,如:
void printf(const char* format, …);
直到最近,可变参数表还是只能应用在真正的函数中,不能使用在宏中。
C99编译器标准终于改变了这种局面,它允许你可以定义可变参数宏(variadic macros),这样你就可以使用拥有可以变化的参数表的宏。可变参数宏就像下面这个样子:
#define debug(…) printf(__VA_ARGS__)
缺省号代表一个可以变化的参数表。使用保留名 __VA_ARGS__ 把参数传递给宏。当宏的调用展开时,实际的参数就传递给 printf()了。例如:
Debug(“Y = %d\n”, y);
而处理器会把宏的调用替换成:
printf(“Y = %d\n”, y);
因为debug()是一个可变参数宏,你能在每一次调用中传递不同数目的参数:
debug(“test”); //一个参数
可变参数宏不被ANSI/ISO C++ 所正式支持。因此,你应当检查你的编译器,看它是否支持这项技术。
用GCC和C99的可变参数宏, 更方便地打印调试信息
gcc的预处理提供的可变参数宏定义真是好用:
#ifdef DEBUG
#define dbgprint(format,args...) \
fprintf(stderr, format, ##args)
#else
#define dbgprint(format,args...)
#endif
如此定义之后,代码中就可以用dbgprint了,例如dbgprint("aaa %s", __FILE__);。感觉这个功能比较Cool :em11:
下面是C99的方法:
#define dgbmsg(fmt,...) \
printf(fmt,__VA_ARGS__)
新的C99规范支持了可变参数的宏
具体使用如下:
以下内容为程序代码:
#include <stdarg.h> #include <stdio.h>
#define LOGSTRINGS(fm, ...) printf(fm,__VA_ARGS__)
int main() { LOGSTRINGS("hello, %d ", 10); return 0; }
但现在似乎只有gcc才支持。
可变参数的宏里的‘##’操作说明
带有可变参数的宏(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参数一样,这些参数不是宏的扩展。
怎样写参数个数可变的宏
一种流行的技巧是用一个单独的用括弧括起来的的 ``参数" 定义和调用宏, 参数在 宏扩展的时候成为类似 printf() 那样的函数的整个参数列表。
#define DEBUG(args) (printf("DEBUG: "), printf args)
if(n != 0) DEBUG(("n is %d\n", n));
明显的缺陷是调用者必须记住使用一对额外的括弧。
gcc 有一个扩展可以让函数式的宏接受可变个数的参数。 但这不是标准。另一种 可能的解决方案是根据参数个数使用多个宏 (DEBUG1, DEBUG2, 等等), 或者用 逗号玩个这样的花招:
#define DEBUG(args) (printf("DEBUG: "), printf(args))
#define _ ,
DEBUG("i = %d" _ i);
C99 引入了对参数个数可变的函数式宏的正式支持。在宏 ``原型" 的末尾加上符号 ... (就像在参数可变的函数定义中), 宏定义中的伪宏 __VA_ARGS__ 就会在调用是 替换成可变参数。
最后, 你总是可以使用真实的函数, 接受明确定义的可变参数
如果你需要替换宏, 使用一个 函数和一个非函数式宏, 如 #define printf myprintf。
在 GNU C 中,宏可以接受可变数目的参数,就象函数一样,例如:
#define pr_debug(fmt,arg...) \
printk(KERN_DEBUG fmt,##arg)
用可变参数宏(variadic macros)传递可变参数表
你可能很熟悉在函数中使用可变参数表,如:
void printf(const char* format, …);
直到最近,可变参数表还是只能应用在真正的函数中,不能使用在宏中。
C99编译器标准终于改变了这种局面,它允许你可以定义可变参数宏(variadic macros),这样你就可以使用拥有可以变化的参数表的宏。可变参数宏就像下面这个样子:
#define debug(…) printf(__VA_ARGS__)
缺省号代表一个可以变化的参数表。使用保留名 __VA_ARGS__ 把参数传递给宏。当宏的调用展开时,实际的参数就传递给 printf()了。例如:
Debug(“Y = %d\n”, y);
而处理器会把宏的调用替换成:
printf(“Y = %d\n”, y);
因为debug()是一个可变参数宏,你能在每一次调用中传递不同数目的参数:
debug(“test”); //一个参数
可变参数宏不被ANSI/ISO C++ 所正式支持。因此,你应当检查你的编译器,看它是否支持这项技术。
用GCC和C99的可变参数宏, 更方便地打印调试信息
gcc的预处理提供的可变参数宏定义真是好用:
#ifdef DEBUG
#define dbgprint(format,args...) \
fprintf(stderr, format, ##args)
#else
#define dbgprint(format,args...)
#endif
如此定义之后,代码中就可以用dbgprint了,例如dbgprint("aaa %s", __FILE__);。感觉这个功能比较Cool :em11:
下面是C99的方法:
#define dgbmsg(fmt,...) \
printf(fmt,__VA_ARGS__)
新的C99规范支持了可变参数的宏
具体使用如下:
以下内容为程序代码:
#include <stdarg.h> #include <stdio.h>
#define LOGSTRINGS(fm, ...) printf(fm,__VA_ARGS__)
int main() { LOGSTRINGS("hello, %d ", 10); return 0; }
但现在似乎只有gcc才支持。
可变参数的宏里的‘##’操作说明
带有可变参数的宏(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参数一样,这些参数不是宏的扩展。
怎样写参数个数可变的宏
一种流行的技巧是用一个单独的用括弧括起来的的 ``参数" 定义和调用宏, 参数在 宏扩展的时候成为类似 printf() 那样的函数的整个参数列表。
#define DEBUG(args) (printf("DEBUG: "), printf args)
if(n != 0) DEBUG(("n is %d\n", n));
明显的缺陷是调用者必须记住使用一对额外的括弧。
gcc 有一个扩展可以让函数式的宏接受可变个数的参数。 但这不是标准。另一种 可能的解决方案是根据参数个数使用多个宏 (DEBUG1, DEBUG2, 等等), 或者用 逗号玩个这样的花招:
#define DEBUG(args) (printf("DEBUG: "), printf(args))
#define _ ,
DEBUG("i = %d" _ i);
C99 引入了对参数个数可变的函数式宏的正式支持。在宏 ``原型" 的末尾加上符号 ... (就像在参数可变的函数定义中), 宏定义中的伪宏 __VA_ARGS__ 就会在调用是 替换成可变参数。
最后, 你总是可以使用真实的函数, 接受明确定义的可变参数
如果你需要替换宏, 使用一个 函数和一个非函数式宏, 如 #define printf myprintf。
发表评论
-
c++ 读取unicode文档
2015-02-09 16:12 961int ReadOneNameFile(char *fil ... -
http://curl.haxx.se/
2013-06-13 17:41 0http://curl.haxx.se/ -
[转]线程本地存储(Thread Local Storage, TLS)分析与使用
2013-05-03 16:53 806线程本地存储(Thread Local Storage, TL ... -
C/C++获得windows版本
2012-12-01 11:05 1464MSDN上有详细介绍,做个标记: #include & ... -
[转]异常处理与MiniDump详解(4) MiniDump
2012-10-24 14:46 964异常处理与MiniDump详解(4) MiniDump wri ... -
禁用系统硬错误消息对话框
2012-08-31 19:14 721http://support.microsoft.com/kb ... -
Application Crash Dump Analysis (Windows 7)
2012-08-28 09:39 0Application Crash Dump Analysis ... -
如何成为一个windows程序debug高手
2012-08-18 14:40 0minidump: http://blog.csdn.ne ... -
Boost库编译后命名方式
2012-05-17 10:29 1346Boost官网的《Geting Started ... -
geoIP
2012-05-14 12:38 0http://www.oschina.net/code/sni ... -
vs2010 断点 无法命中
2012-05-07 16:13 1355这种情况不解决办法有 很多。你这个方法我没用过。最简单的方法就 ... -
$err,hr
2012-05-04 20:43 914在Visual C++ 中,可以在监视窗口添加 $err,hr ... -
WINDOWS下线程同步探讨
2012-04-11 15:04 947概述 线程同步可 ... -
undefined reference to 'pthread_create'问题解决
2012-03-30 11:43 0由于是Linux新手,所以现在才开始接触线程编程,照着GUN/ ... -
linux 下 遍历文件夹下的内容
2012-03-29 19:43 0// only works in cpp #ifdef __c ... -
浅谈ReadDirectoryChangesW函数的作用和问题所在
2012-03-23 10:32 4323转自:http://www.cnblogs.com ... -
用 _findfirst 和 _findnext 查找文件,遍历文件夹
2012-03-30 11:39 2019标签: _findfirst _findnext 杂谈 分类: ... -
我的广告
2012-03-19 10:57 0http://www.webweb.com/signup.as ... -
服务器多服务器设置
2012-03-12 18:01 753当服务器功能比较多时,可以抽象出一个代理,将不同的服务 ... -
记录个函数 strstr
2012-03-10 11:30 1037包含文件:string.h 函数名: strstr 函 ...
相关推荐
`__VA_ARGS__` 是一个宏,它代表可变参数列表中的实际参数。 - `__FILE__`: 这个宏在预编译时会被替换成当前源文件的完整路径。 - `__LINE__`: 这个宏在预编译时会被替换成当前行号。 - `__FUNCTION__`: 这个宏在预...
当在其他可变参数宏中使用VA_ARGS_COUNT()宏时,它确实发光。 您可能有一个函数,需要使用可变数量的参数,如下所示: void print_strings(int count, const char *s1, ...); 其中第一个参数count指定传递给该...
在C/C++编程语言中,`#`、`##` 和 `__VA_ARGS__` 是预处理器宏中的特殊符号,它们在处理可变参数宏时起着关键作用。本文将详细探讨这三个符号以及它们在可变参数函数中的应用。 ### 1. `#` 符号 `#` 符号在宏定义...
本文介绍了C语言中特殊符号 `#` 和 `##` 的用法以及可变参数宏 `__VA_ARGS__` 的应用。通过具体的示例代码,我们可以看到如何利用这些特性来编写更加灵活和强大的宏。`#` 操作符可以帮助我们在运行时生成动态文本...
### C语言可变参数机制详解:`va_list`与`vsnprintf`及`printf`实现 #### 引言 在C语言编程中,我们经常使用`printf`函数来输出各种格式的数据,但你是否曾思考过,这个看似简单的函数背后隐藏着怎样的复杂性?`...
今天,我们将讨论 C、C++ 中的变参数宏,包括可变参数宏和 _VA_ARGS_ 的使用。 一、可变参数宏 可变参数宏是 C 语言中的一种特殊宏定义,允许宏定义中包含可变数量的参数。这种宏定义使用省略号(...)来表示可变...
### C语言可变参数函数实现探究 ...总之,可变参数函数是C语言中一个强大且灵活的功能,通过合理利用`_va_list`和相关宏,可以构建出能够处理动态参数数量的高效函数,这对于编写复杂多变的应用程序具有重要意义。
`va_start`、`va_arg`和`va_end`是三个关键宏,它们分别用于初始化可变参数列表、获取下一个参数和清理资源。 1. **`va_start`宏**:用于初始化`va_list`。它的语法是`va_start(list, lastFixedArg)`,其中`list`是...
`__VA_ARGS__` 是可变参数宏的一个特殊占位符,用于访问宏定义中带有不定数量参数的列表。它通常与 `...` 结合使用。例如,你可以定义一个打印任意数量参数的宏: ```cpp #define PRINT(...) printf(__VA_ARGS__)...
首先,`__VA_ARGS__` 是预处理器宏中的一个特殊符号,主要用于宏定义中的可变参数。当定义一个宏,如: ```cpp #define PRINTF_FORMATTED(...) printf(__VA_ARGS__) ``` 在这个例子中,`__VA_ARGS__` 会捕获宏调用...
C语言可变参数实现机制详解 ...我们可以通过 va_list 和 vsnprintf 等机制来实现可变参数的函数,并且可以通过栈操作来确定可变参数的位置。但是,这只是一个简单的示例代码,实际上还需要根据具体情况进行调整和优化。
在这个例子中,`__VA_ARGS__` 是一个特殊标识符,用于代表传递给宏的可变参数列表。例如: ```c myprintf("Error: %s\n", "Something went wrong"); ``` 上述调用等价于: ```c fprintf(stderr, "Error: %s\n", ...
在C语言中,可变参数的实现基于调用约定(calling convention),通常涉及到两个关键函数:`va_start`、`va_end` 和一个宏 `va_list`。`va_list` 是一个类型定义,用于存储可变参数列表的指针;`va_start` 用于初始...
`va_start`是用于初始化可变参数列表的宏。它的语法如下: ```cpp va_start(ap, last_fixed_arg); ``` 这里的`ap`是一个指向可变参数列表的指针(通常是一个`va_list`类型的变量),`last_fixed_arg`是可变参数...
2. `va_start`:这个宏用于初始化`va_list`,告诉编译器从哪个参数开始处理可变参数。它的语法是`va_start(args, last_fixed_arg)`,其中`args`是`va_list`变量,`last_fixed_arg`是函数定义中最后一个固定参数的...
这些宏提供了访问和遍历可变参数列表的方法。`va_start`初始化`va_list`,`va_arg`用于获取下一个参数,而`va_end`在使用完所有参数后结束访问。 #### 结论 通过以上分析,我们可以看到,尽管可变参数函数在编写时...
总结来说,C/C++中的可变参数宏是通过`...`和`__VA_ARGS__`来实现的,`##`运算符则用于处理空参数时的逗号问题。GCC提供了额外的扩展,使得宏的使用更加灵活,但同时也需要开发者更加注意可能的陷阱。在实际编程中,...
`va_start`宏用于初始化`va_list`指针,使其指向可变参数列表的开始。它的两个参数分别是`va_list`指针和最后一个固定参数。例如,`va_start(arg_ptr, i)`,其中`i`是`simple_va_fun`函数中最后一个已知参数,`arg_...