面试题答案
一键面试宏函数与普通函数在性能优化方面的区别
- 代码展开方式
- 宏函数:在预处理阶段,宏函数被预处理器直接展开到调用处。这意味着没有函数调用的开销,如参数压栈、跳转到函数地址、返回等操作。例如定义宏函数
#define ADD(a, b) ((a) + (b))
,当ADD(3, 5)
调用时,预处理器会直接将其替换为((3) + (5))
。 - 普通函数:在运行时进行函数调用。每次调用函数都需要进行参数传递、保存寄存器状态、跳转到函数执行代码处,执行完毕后再返回,存在一定的性能开销。例如定义函数
int add(int a, int b) { return a + b; }
,调用add(3, 5)
时会有上述函数调用开销。
- 宏函数:在预处理阶段,宏函数被预处理器直接展开到调用处。这意味着没有函数调用的开销,如参数压栈、跳转到函数地址、返回等操作。例如定义宏函数
- 类型检查
- 宏函数:宏函数不进行类型检查,只是简单的文本替换。如果宏函数使用不当,比如参数类型不匹配,可能导致难以发现的错误。例如
ADD(3.5, 5)
,宏函数会将其替换为((3.5) + (5))
,但如果是普通函数add
,传递浮点数会因类型不匹配而报错(假设函数定义为int
类型参数)。 - 普通函数:普通函数在编译时会进行严格的类型检查,保证参数类型与函数定义一致,增强了程序的健壮性。
- 宏函数:宏函数不进行类型检查,只是简单的文本替换。如果宏函数使用不当,比如参数类型不匹配,可能导致难以发现的错误。例如
利用宏函数特性进行简单性能优化示例
假设需要在循环中频繁计算两个数的和,使用宏函数可以减少函数调用开销从而提升性能。
#include <stdio.h>
#define ADD(a, b) ((a) + (b))
int main() {
int sum = 0;
for (int i = 0; i < 1000000; i++) {
sum = ADD(sum, i);
}
printf("Sum: %d\n", sum);
return 0;
}
在上述代码中,循环中每次调用 ADD
宏函数,由于宏函数在预处理阶段直接展开,没有函数调用开销,相比使用普通函数,在这种频繁调用的场景下能提升一定的性能。