#与##在宏定义中的--宏展开
#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
  printf("%s/n", h(f(1,2))); // 12
  printf("%s/n", g(f(1,2))); // f(1,2)
  return 0;
}
宏展开时:
如果宏定义以#开头,不展开参数,直接替换。
故g(f(1,2))--->#f(1,2)--->"f(1,2)";
如果宏定义不以#开头,展开参数,直接替换,由外层向里层,如果碰到的是#开头的宏,不继续往里层展开,往外层展开。
由外层向里层,如果碰到的是以非#开头的宏,继续往里层走,直至最里层,开始一层层往外层展开。
故h(f(1,2))--->h(12)--->g(12)---->#12----->"12"。
PS:
##在宏中定义,是字符连接符
如a##b##c 等同于 "abc"
#在宏开头出现,是表示宏展开的方式不同
#a 等同于"a"
#abc 等同于 "abc"
复杂的:
#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
  char a = 'a';
  cout<<g(a)<<endl; // a
  cout<<g(g(a))<<endl; // a
  printf("%s/n", h(f(1,2))); // 12
  printf("%s/n", g(f(1,2))); // f(1,2)
  printf("%s/n", g(h(f(1,2)))); // h(f(1,2))
  printf("%s/n", h(g(f(1,2)))); // "f(1,2)"
  printf("%s/n", h(h(f(1,2)))); // "12"
  system("pause");
  return 0;
}
预处理后的:(在编译选项中添加/EP /P后编译生成的.i文件)
int main()
{
  char a = 'a';
  cout<<"a"<<endl;
  cout<<"g(a)"<<endl;
  printf("%s/n", "12");
  printf("%s/n", "f(1,2)");
  printf("%s/n", "h(f(1,2))");
  printf("%s/n", "/"f(1,2)/"");
  printf("%s/n", "/"12/"");
  system("pause");
  return 0;
}
---------------------------------------------------
宏解析
1. ##操作符
##操作符它的作用是在替代表中将其前后的参数连接成为一个预处理符号,它不能出现于宏替代表的开端和末尾。
例:
#define concat(s,t) s##t
#define AAA ABC
concat(A, AA)
将被替换成
ABC
2. 重新扫描和替换
在替换列表中的所有参数替换过之后,预处理器将对结果token序列重新扫描以便对其中的宏再次替换。
当正在替换的宏在其替换列表中发现自身时,就不再对其进行替换。今儿,在任何正在嵌套替换的宏的替换过程中遇到正被替换的宏就对其不再进行替换(防止递归)。
例:
#define ROOT AAA CCC
#define AAA ROOT
ROOT
将被替换成
ROOT CCC

转载于:https://www.cnblogs.com/pang123hui/archive/2011/02/25/2309915.html

#与##在宏定义中的--宏展开相关推荐

  1. define宏定义中的#,##,@#及\符号

    define宏定义中的#,##,@#及\符号 在#define中,标准只定义了#和##两种操作.#用来把参数转换成字符串,##则用来连接两个前后两个参数,把它们变成一个字符串. 1.# (string ...

  2. 宏定义中#号和##号的使用

    在技术群中有人提了一个问题:如何定义一个宏,打印传递过来的参数的地址.这很简单,像下面这样 [objc] view plaincopy #define pl(param)  NSLog(@" ...

  3. #define宏定义中的#,##,@#,\ 这些符号的神奇用法

    C/C++ 宏命令的神奇用法. 先看下面三条语句: #define Conn(x,y) x##y #define ToChar(x) #@x #define ToString(x) #x 1 2 3 ...

  4. ANSI C and Microsoft C++中常用的预定义宏以及 宏定义中 # 和 ## 的区别

    ANSI C and Microsoft C++中常用的预定义宏以及 宏定义中 # 和 ## 的区别 第一部分,常见的预定义宏 第二部分,# 和 ## 再宏定义中的使用说明 第三部分,类似 #prag ...

  5. c语言长度宏定义运算符,C语言在宏定义中使用语句表达式和预处理器运算符

    语句表达式的亮点在于定义复杂功能的宏.使用语句表达式来定义宏,不仅可以实现复杂的功能,而且还能避免宏定义带来的歧义和漏洞.下面以一个简单的最小值的宏为例子一步步说明. 1.灰常简单的么,使用条件运算符 ...

  6. c程序语言符号的作用,c语言宏定义中的#,##,#@及\符号的作用

    1.#(stringizing)字符串化操作符 作用:将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串.其只能用于有传入参数的宏定   义中,且必须置于宏定义体中的参数名前. 如: #def ...

  7. C语言 带参数宏定义中 # 和 ## 知识点总结、代码分析

    目录 一.宏定义中 "#"知识点 1.直接转换字符串,不展开. 2.转换出的结果一定是"字符串". 二.宏定义中 ## 知识点 1.应用场景 2."# ...

  8. do...while(0)在宏定义中的巧妙用法

    大家都知道,do-while(condition)可以表示循环,但你有没有遇到在一些宏定义中可以不用循环的地方,也用到了 do-while.比如: #define DELETE_POINTER(p) ...

  9. 宏定义中的 ## ... __VA_ARGS__

    宏定义中的##操作符和... and _ _VA_ARGS_ _ 1.Preprocessor Glue: The ## Operator 预处理连接符:##操作符 Like the # operat ...

最新文章

  1. 自定义Counter使用
  2. 高校教授称已推翻爱因斯坦相对论,项目还被推荐入选河北科学技术奖?!回应来了!...
  3. 三菱fb功能块手册中文_技成周报33期 | 三菱、西门子全系列这34个问题值得一看!...
  4. 2020年十大数据中心行业趋势
  5. PyQt4编程之如何让状态栏显示信息
  6. 基于报文地址的策略路由配置示例
  7. 设备 esp32_「ESP 教程」ESP32 如何运行 TensorFlow 模型
  8. 图像采样、量化、编码(二十七)
  9. c语言记账系统源程序,C语言会计记账管理系统.doc
  10. 从图书馆进入网络刷题练习与考试平台
  11. activiti流程图下发任务报错,不能正常流转到下一个处理步骤
  12. C语言:开平方判断素数
  13. 【NanoPi T2】 6.uboot gmac网卡驱动(2) - 寄存器介绍
  14. ZigZag Conversion(“Z”形转换)
  15. linux备份软件rear,linux系统 备份与还原
  16. android java join_java中的join用法
  17. STM32单片机硬件I2C读取AHT10温湿度传感器数据
  18. python expandtabs_详解Python中expandtabs()方法的使用
  19. 在Openshift上部署asp.net遇到的一些捉急问题总结
  20. 首发!小牛电动股权巨震:李一男、胡依林大幅减持,纪源资本退出

热门文章

  1. SharePoint品牌化和自定义--第三章节--收集品牌化需求(3)--要当心的地方
  2. 为什么用 抽象类,接口
  3. 用Java模拟multipart形式的Http Post请求
  4. PHP学习笔记二: 面向对象设计
  5. 片(Slice)结构
  6. supesite之空间篇
  7. vue导航栏跳转路由
  8. 日本奥委会主席否认为争取奥运会主办权行贿
  9. LOJ#2127「HAOI2015」按位或
  10. open-v-p-n原理解读及实例服务部署