宏定义的高级用法和#、##替代用法
来源:互联网 发布:java薪水 编辑:程序博客网 时间:2024/06/05 14:45
1.宏中的#的功能是将其后面的宏参数进行字符串化操作(Stringizing operator),简单说就是在它引用的宏变量的左右各加上一个双引号。
2.#-强制转化成加双引号的字符;
3.##-强制去掉前后空格,连接字符串
4.也就是说# ##都是基于字符串操作的
5.# 与##不能同时在一个宏中使用
(1)# When you put a # before an argument in a preprocessor macro, the preprocessor turns that argument into a character array.
在一个宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组
简化理解:#是“字符串化”的意思,出现在宏定义中的#是把跟在后面的参数转换成一个字符串
#define ERROR_LOG(module) fprintf(stderr,"error: "#module"\n")
ERROR_LOG("add"); 转换为 fprintf(stderr,"error: "add"\n");
ERROR_LOG(devied =0); 转换为 fprintf(stderr,"error: devied=0\n");
(2)##
“##”是一种分隔连接方式,它的作用是先分隔,然后进行强制连接。
在普通的宏定义中,预处理器一般把空格解释成分段标志,对于每一段和前面比较,相同的就被替换。但是这样做的结果是,被替换段之间存在一些空格。如果我们不希望出现这些空格,就可以通过添加一些##来替代空格。
1 #define TYPE1(type,name) type name_##type##_type2 #define TYPE2(type,name) type name##_##type##_type
TYPE1(int, c); 转换为:int name_int_type ; (因为##号将后面分为 name_ 、type 、 _type三组,替换后强制连接)
TYPE2(int, d);转换为: int d_int_type ; (因为##号将后面分为 name、_、type 、_type四组,替换后强制连接)
3、宏定义中do{ }while(0)
第一眼看到这样的宏时,觉得非常奇怪,为什么要用do……while(0)把宏定义的多条语句括起来?非常想知道这样定义宏的好处是什么,于是google、百度一下了。
采用这种方式是为了防范在使用宏过程中出现错误,主要有如下几点:
(1)空的宏定义避免warning:
#define foo() do{}while(0)
(2)存在一个独立的block,可以用来进行变量定义,进行比较复杂的实现。
(3)如果出现在判断语句过后的宏,这样可以保证作为一个整体来是实现:
#define foo(x) \
action1(); \
action2();
在以下情况下:
if(NULL == pPointer)
foo();
就会出现action1和action2不会同时被执行的情况,而这显然不是程序设计的目的。
(4)以上的第3种情况用单独的{}也可以实现,但是为什么一定要一个do{}while(0)呢,看以下代码:
#define switch(x,y) {int tmp; tmp="x";x=y;y=tmp;}
if(x>y)
switch(x,y);
else //error, parse error before else
otheraction();
在把宏引入代码中,会多出一个分号,从而会报错。这对这一点,可以将if和else语句用{}括起来,可以避免分号错误。
使用do{….}while(0) 把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低
(4)宏嵌套
宏中遇到#或##时就不会再展开宏中嵌套的宏了。什么意思了?比如使用char *pChar = STRING(__FILE__);虽然__FILE__本身也是一个宏,但编译器不会展开它,所以pChar将指向"__FILE__"而不是你要想的形如"D:\XXX.cpp"的源文件名称。因此要加一个中间转换宏,先将__FILE__解析成"D:\XXX.cpp"字符串。
定义如下所示二个宏:
#define _STRING(x)#x
#define STRING(x)_STRING(x)
再调用下面语句将输出带""的源文件路径
char* pChar = STRING(__FILE__);
printf("%s %s\n",pChar, __FILE__);
可以比较下STRING(__FILE__)与__FILE__的不同,前将带双引号,后一个没有双引号。
- 宏定义的高级用法和#、##替代用法
- 宏定义的高级用法
- C语言宏定义高级用法总结
- 宏的高级用法# ##
- 宏定义符号#和##的用法
- 宏定义和const的用法
- 宏定义和const的用法
- C宏定义#和##的用法
- C语言:宏定义的#和##用法
- cellpadding的用法和定义
- 枚举的定义和用法
- mysqli_query 的定义和用法
- 接口的定义和用法
- 语句的定义和用法
- 宏定义 # 和 ## 用法总结
- "||" 和 "&&"高级用法
- 宏定义中"#"的用法
- Freemarker定义宏的用法
- CSS中!improtant的使用
- iOS开发 创建自己的UserAgent
- OPEN TSDB - 基于时间的数据库
- 反射机制
- Eclipse配置 JOnAS服务器
- 宏定义的高级用法和#、##替代用法
- [转]Android Matrix利用invert实现逆向坐标映射
- 安装android studio报错Failed to install Intel HAXM
- C++Primer 第五版 9.3.1节练习
- python pip安装 PIL
- 轻松自动化---selenium-webdriver(python) (七)
- 随机数生成算法
- SQL语句大全
- 查看mysql版本的四种方法