大部分从Java之后的编程语言都不支持宏,因为它们离C语言偏远。一个例外是C#, 它总是如此调皮。
什么是宏?
- 宏,是一种批量处理的称谓。计算机科学中,代表根据一系列预定义的规则替换一定的文本模式。宏起源于汇编语言macro替换。
- 宏用于预处理,在编译之前,sizeof是编译期计算,它是在预处理之后,所以不能将sizeof放到预处理指令中判断。
编程语言不同标准
- C/C++经常利用宏来指明编译器对应标准的版本。比如
#define__STDC_VERSION__ 201112L
代表C11. 此宏可让程序员根据不同语言标准写不同的代码,在底层代码中尤为有效。MSVC可用_MSC_VER和_MSC_FULL_VER等宏来代表不同编译器版本。
宏排错
- 避免在整形变量小于32位的机器上使用:
#if INT_MAX <= 32767
#error “Int should be over 2 bytes”
#endif - 有一段代码,为了确定在哪句发生问题,可封装包含__FILE__和__LINE__、__func__宏的语句二分查找出错的位置。
- 每次release一个新版本,为了记录版本,避免用错版本,利用__DATE__和__TIME__记录版本编译时间。
编译选项
- C语言支持-D或-U定义或取消定义一个宏变量。
宏和注释
- 宏定义后面紧跟着注释,注释并不会被当做宏扩展的一部分,原因在于预处理会先去除注释。
- #define YOUR_MACRO do_something() // This will do something
宏和字符串
- #可将符号转换成”字符串”格式。
- 宏扩展不能扩展到字符串里面的"标识符",因为字符串内部的字符都被看做字符串一部分,而非标识符。
作用范围
- 宏作用范围是当前出现处到文件结尾,哪怕当前出现在函数内部。
- 如遇到此宏的 #undef 则作用域结束。
宏嵌套
因为宏的原始性,不像函数,编译器很轻松了解程序员的意图。宏替换嵌套可能导致完全不同的理解方式,为此,形成了一套最基本的宏替换原则。
- 宏替换总是从最外层开始解析。
- 如果包含#或者##或者是最内层,直接做当前层替换;否则,进入内一层重复此过程继续处理。
- 当第2步执行完替换,检查表达式是否还有宏,如有继续上面第1步,如没有即结束。