一、#用来把参数转换成字符串

例子一:

#define P(A) printf("%s:%d\n",#A,A);

int main(int argc, char **argv)

{
        int a = 1, b = 2;

P(a);

P(b);

P(a+b);

system("pause");

}

输出为:

例子二:

#define SQUARE(x) printf("The square of "#x" is %d.\n", ((x)*(x)));

SQUARE(8)

输出的是:The square of 8 is 64

二、##运算符可以用于宏函数的替换部分。这个运算符把两个语言符号组合成单个语言符号,为宏扩展提供了一种连接实际变元的手段

例子一:

#define XNAME(n) x ## n

如果这样使用宏:XNAME(8)

则会被展开成这样:x8

##就是个粘合剂,将前后两部分粘合起来,也就是有“字符化”的意思。但是“##”不能随意粘合任意字符,必须是合法的C语言标示符。在单一的宏定义中,最多可以出现一次“#”或“##”预处理操作符。如果没有指定与“#”或“##”预处理操作符相关的计算次序,则会产生问题。为避免该问题,在单一的宏定义中只能使用其中一种操作符(即,一份“#”或一个“##”,或都不用)。除非非常有必要,否则尽量不要使用“#”和“##”。

三、__VA_ARGS__ 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。
实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。

四、##__VA_ARGS__ 宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错

一般这个用在调试信息上多一点

例如:

#define my_print1(...)  printf(__VA_ARGS__)   my_print1("i=%d,j=%d\n",i,j)  正确打印

#define my_print2(fmt,...)  printf(fmt,__VA_ARGS__)

my_print1("i=%d,j=%d\n",i,j) 正确打印

my_print2("iiiiiii\n")       编译失败打印,因为扩展出来只有一个参数,至少要两个及以上参数

如果是#define my_print2(fmt,...)  printf(fmt,##__VA_ARGS__)

那么

my_print1里面不管是几个参数都能正确打印

#define MODULE_NAME "MY_LIBS"
 
#define error_printf(fmt,...) printf("[ERROR]["MODULE_NAME"](%s|%d)"fmt,__func__,__LINE__,##__VA_ARGS__)
————————————————
版权声明:本文为CSDN博主「侵蚀昨天」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/q2519008/article/details/80934815

#、##、__VA_ARGS__和##__VA_ARGS__的作用相关推荐

  1. C语言 函数不定长参数 ##__VA_ARGS__经典案例 - C语言零基础入门教程

    目录 一.##__VA_ARGS__简介 二.##__VA_ARGS__经典案例 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.## ...

  2. C语言 ##__VA_ARGS__ - C语言零基础入门教程

    目录 一.##__VA_ARGS__原理 二.##__VA_ARGS__使用 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.##__ ...

  3. C语言 __VA_ARGS__ - C语言零基础入门教程

    目录 一.__VA_ARGS__简介 二.__VA_ARGS__使用 1.__VA_ARGS__宏输出字符串常量 2.__VA_ARGS__宏输出可变参数 三.__VA_ARGS__缺点 1.仅仅只支 ...

  4. makefile使用宏及用法$(宏标识符) $(cc)_宏编程的艺术

    微信限制:不能放置链接,代码样式比较奇怪,发布后不能更新... 推荐 阅读原文: 写在前面 之前写过几篇关于 C/C++ 宏 (macro) 和 C++ 元编程 (metaprogramming) 的 ...

  5. C++ 预处理与宏相关编程(#,##等等)

    一.简介引言 C++ 模板元编程 (template metaprogramming) 虽然功能强大,但也有 局限性: 不能通过 模板展开 生成新的 标识符(identifier).例如:生成新的 函 ...

  6. 插头DP 概率DP / 期望DP

    插头DP && 概率DP / 期望DP 写在前面: 插头DP P5056 [模板]插头dp 手写哈希表的方法: 拉链法的代码如下: 开放寻址法的代码如下: 接下来是这道题的代码实现: ...

  7. ...可变形参的使用

    可变行参f(-)使用 #define va_start(ap, A) #define va_end(ap) #define va_arg(ap, T) 例如:f(a,-) va_list ap; va ...

  8. Android 6.0 JNI原理分析 和 Linux系统调用(syscall)原理

    JNI原理 引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: fram ...

  9. 虚幻引擎之多线程渲染机制

    虚幻引擎之多线程渲染机制 文章目录 虚幻引擎之多线程渲染机制 一.前言 二.游戏线程与渲染线程的交互 2.1 ENQUEUE_RENDER_COMMAND宏 2.2 渲染线程 2.3 数据交互 2.3 ...

最新文章

  1. 30多条mysql数据库优化方法,千万级数据库记录查询轻松解决
  2. Py之pandas:字典格式数据与dataframe格式数据相互转换并导出到csv
  3. 鲁迅文学院60周年庆
  4. android json传输数据到服务器,Android中post请求传递json数据给服务端的实例
  5. block--内存管理
  6. U3D开发的逆天级大型游戏有哪些
  7. 解决能上QQ却不能上网的问题
  8. 您未被授权查看该页; HTTP 错误 401.1 - 未经授权:访问由于凭据无效被拒绝。
  9. win7万能声卡驱动_驱动精灵标准版 v9.61.3708.3054下载
  10. notepad下载(官网进不去)
  11. 文件操作eof()的问题
  12. AutoJs学习-快手组队助力脚本
  13. 夕拾朝花——我的2016
  14. 绿色版 MySQL 安装配置的正确操作步骤
  15. 2013-2014 NBA 东西部决赛 + 总决赛合集
  16. 取证技术---电子数据取证技术基础知识点
  17. 刘海屏下悬浮球的位置计算
  18. Libev源码分析08:Libev中的信号监视器
  19. 线性代数学习笔记——第四十五讲——线性相关性的判定
  20. 固态硬盘分区电脑分区软件

热门文章

  1. linux内核c1bcbc40,Linux内核驱动
  2. 【转】很全的英语短语
  3. 微信小程序 - 跨域问题
  4. SI,SIS,SIR,SEIRD模型
  5. Linux的远程终端连不上,Linux系统远程连接终端连接不上怎么办
  6. 学习淘淘商城第二课(搭建Maven工程)
  7. 腾讯、阿里之后,今日头条也入局的视频通信行业!
  8. 基于遗传算法优化的Elman神经网络数据预测-附代码
  9. 【附源码】计算机毕业设计JAVA在线购书商城系统
  10. 开源视频播放器IjkPlayer使用记录之一--demo的使用及View的简要介绍