1. #的作用是将宏参数字符串化,

例如下面的宏定义

#define STR( s ) #s

那么在程序中

printf("The string is %s/n", STR(OPEN) );

会被展开成

printf("The string is %s/n", "OPEN" );

也就是说,会对#后跟的参数加引号,使其变成一个字符串。

2. ##的作用是对文本进行连接

例如下面的宏定义

#define  CONS( a, b ) a##e##b

那程序中

printf("the number is %d/n", CONS(2,3) );

会被展开成

printf("the number is %d/n", 2e3 );

需要注意的是,在有#和##的宏中,如果参数本身是宏,则这个参数宏不会展开。

加一层中间转换宏可以解决这个问题。

#define _STR(s)     #s 
#define STR(s)      _STR(s)          // 转换宏 
#define _CONS(a,b)  int(a##e##b) 
#define CONS(a,b)   _CONS(a,b)       // 转换宏

3.综合理解

至于为什么加##进行分隔,举个例子容易理解,比如#define F(x) T##x##_,如果前面的##不加,则Tx##_,其中的Tx,编译器就无法识别里面的x是参数里给的x,而是Tx当成一起得了,后面的也类似,总之,加##就是为了把参数识别出来,如果在开头,只加后面的就可以了,如x##_

简单的说,##就是把参数当成不带引号的字符串进行替换,#把参数当成带引号的字符串进行替换

## 连接符号由两个井号组成,其功能是在带参数的宏定义中将两个子串(token)联接起来,从而形成一个新的子串。但它不可以是第一个或者最后一个子串。所谓的子串(token)就是指编译器能够识别的最小语法单元。具体的定义在编译原理里有详尽的解释,但不知道也无所谓。同时值得注意的是#连接符是把传递过来的参数当成字符串进行替代。下面来看看它们是怎样工作的。这是MSDN上的一个例子。

  假设程序中已经定义了这样一个带参数的宏:
#define paster( n ) printf( "token" #n " = %d", token##n )
  同时又定义了一个整形变量:
int token9 = 9;
  现在在主程序中以下面的方式调用这个宏:
paster( 9 );
  那么在编译时,上面的这句话被扩展为:
printf( "token" "9" " = %d", token9 );
详细解说:#n 相当于 “n”, token##n 相当于token9,须注意##不能当成两个#,他们意义是不同的。
  
注意到在这个例子中,paster(9);中的这个”9”被原封不动的当成了一个字符串,与”token”连接在了一起,从而成为了token9。而#n也被”9”所替代。
  可想而知,上面程序运行的结果就是在屏幕上打印出token9=9

注意##和#的使用场合,不能乱用。

C宏定义中## 和# 的含义相关推荐

  1. C语言宏定义中UL的含义

    1.U表示 unsigned 无符号,L表示 long 长整数.后缀大小写都可以,可以单独使用(100U),也可以组合使用(100UL). 2.F表示float,但是F不可以和U组合,因为浮点数没有u ...

  2. (转载) min()的宏定义中的(void) (_x == _y)的含义

    Original Address:http://www.crifan.com/2010/08/13/order_min__macro_definition_void_amp__x__amp__y_th ...

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

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

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

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

  5. #与##在宏定义中的--宏展开

    #与##在宏定义中的--宏展开 #include <stdio.h> #define f(a,b) a##b #define g(a) #a #define h(a) g(a) int m ...

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

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

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

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

  8. do {...} while (0) 在宏定义中的作用

    有篇文章解释很清楚:do {...} while (0) in macros 然后,一位女程序媛把它翻译了一遍,排版清晰,想省力的看这边.do {...} while (0) 在宏定义中的作用

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

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

最新文章

  1. mysql 临时列_如何在MySQL中列出临时表列?
  2. android a z 快速定位,快速集成android实现listview的字母A-Z排序,界面侧边字母索引...
  3. 数据可视化的开源方案: Superset vs Redash vs Metabase (一)
  4. Boost:使用accumulator_set <>和std :: for_each()计算一些有用的统计信息
  5. quartz mysql 初始化_quartz scheduler 从数据库初始化
  6. form表单中根据值判断是否disabled_Java 0基础入门 (Html表单、表单元素)
  7. 如何看待阿里巴巴推荐的Python400集视频?零基础入门学习Python
  8. 数据库---查询操作
  9. 数据可视化建设是企业战略决策之刚需
  10. 图像处理五:python读取图片的几种方式
  11. websocket 发送多条消息如何判断全部接收_Websocket的分布式集群开发及部署
  12. 《推荐系统实践》项亮 书中程序实现
  13. k2路由器linux系统,告别后门:斐讯K2路由器刷入华硕固件
  14. knockoutjs入门要点
  15. python google 搜索结果爬取_对于 Python 抓取 Google 搜索结果的一些了解
  16. 台式计算机显示不了无线网络,我是台式电脑,插上无线网卡怎么我的链接里不显示无线...
  17. QT菜单栏颜色与背景颜色设置
  18. sqlite3_exec返回SQLITE_MISUSE(21)
  19. 《缠中说禅108课》108:何谓底部?从月线看中期走势演化
  20. iOS开发者,金九银十,这样写简历才能让大厂面试官看重你!

热门文章

  1. ocr识别技术-车牌识别一体机的核心关键
  2. Linux的ELF格式分析
  3. Linux 什么时候才能足够完美?
  4. 地球椭球体(Ellipsoid)、大地基准面(Datum)及地图投影(Projection)三者的基本概念
  5. JS开发利器-IxEdit傻瓜式JavaScript开发工具(附下载、汉化版、视频教程)
  6. Java 3.基本数据类型
  7. 流畅的python读书笔记-第一章Python 数据模型
  8. Micropython TPYBoard 智能温控小风扇资料分享
  9. Linux系统调用--getrlimit()与setrlimit()函数详解【转】
  10. iOS:切换视图的第三种方式:UITabBarController标签栏控制器