问题的历史
带参数的宏是C预处理器的重要组成部分,旨在快速引入重复的代码片段并简化调试。它们用于小功能、内联或优化。
问题
宏不检查类型,并且在简单的文本替换之外没有执行完整的替换。由于缺乏括号和涉及副作用的表达式替换,可能会发生错误。
解决方案
在参数和宏定义周围使用括号,避免在参数中出现副作用,并在更复杂的情况下使用内联函数。
代码示例:
#define MAX(a, b) ((a) > (b) ? (a) : (b)) int x = 5, y = 10; int z = MAX(x++, y++); // 危险的调用!
关键特性:
宏是否总是完全像函数一样替换代码?
不!宏只是编译前的文本替换,如果参数是有副作用的表达式,它的行为可能与函数不同。
可以将任何调用(包括++,--)作为宏的参数吗?
这非常危险。如果参数在宏中出现多次,副作用将会发生多次。
代码示例:
// 这个调用会将x或y增加超过1 MAX(x++, y++)
如何正确使用括号来声明宏?
括起宏中的参数和表达式,以避免在其他表达式内调用时出现关联性错误。
在公司,许多年定义了宏#define SQUARE(x) xx,并用于类似SQUARE(a+1)的表达式。出现了意外错误:表达式展开为a+1a+1,这与(a+1)*(a+1)不同。
优点:
宏SQUARE用完整的括号编写:#define SQUARE(x) ((x)*(x))。它的使用已经标准化并记录。
优点: