宏定义
基础用法
宏定义在预处理时会 将常量整体替换而不加以运算 ,不能以为会提前将数值算出而导致错误。例子如下:
#define PI 3.14
#define ABC PI + 1
#include <stdio.h>
int main() {
printf("%f", ABC * 10);
// 预处理时,编译器会直接把所有ABC直接替换为PI + 1
// 所以“ABC * 10”会变为“PI + 1 * 10”,不是想象中的结果
return 0;
}
这段代码输出的是 PI + 1 * 10 的结果,也即13.14,而非41.4。
而如果要想修复这一问题,只要在 ABC 的宏定义处 加上小括号 ,使得被替换处也带有小括号,即可避免因运算符优先级带来的问题。例子如下:
#define PI 3.14
#define ABC (PI + 1)
#include <stdio.h>
int main() {
printf("%f", ABC * 10);
// 预处理时,编译器会直接把所有ABC替换为(PI + 1)
// 所以“ABC * 10”会变为“(PI + 1) * 10”,输出预期中的结果
return 0;
}
这段代码输出的是 (PI + 1) * 10 的结果,也即41.4。
进阶用法
宏定义也能携带参数。例子如下:
#define product(a, b) a * b
// 这里由于a和b被直接替换,所以无需指定a和b的参数类型
#include <stdio.h>
int main() {
int a = 2, b = 3;
int result = product(a + 1, b + 2);
// 注意:直接替换!!!
// 因此该行代码变成:int result = a + 1 * b + 2
printf("%d", result);
return 0;
}
这里同样需要注意 “整体替换” 的问题,C不会自动把 a + 1 和 b + 2 各自识别为一个整体,而是直接将它们替换到指定的位置。因此,为了规避这种问题,有两种解决方案:
- 调用时,为多项式多加一层括号,保证替换后的计算优先级;
- 定义宏时,在
a和b上加上括号,保证a与b各自为一个整体。
也即下面的两种改法:
// 1
int result = product((a + 1), (b + 2));
// 2
#define product(a, b) (a) * (b)
与 JavaScript 的对比
※ JavaScript 中,与 C 宏类似的写法如下:
let product1 = (a, b) => a * b;
let product2 = function(a, b) { return a * b; }
let a = 1, b = 2;
console.log(product1(a + 1, b + 2)); // 8
console.log(product2(a + 1, b + 2)); // 8
[!check] JavaScript 传的是“计算结果”,C 宏传的是“代码文本”。

浙公网安备 33010602011771号