面试题答案
一键面试兼容性问题
- 语法差异:不同编译器对可变参数宏的语法支持略有不同。例如,在较旧的GCC版本中,需要使用特殊的
__VA_ARGS__
语法,而在Visual Studio中语法可能略有差异。 - 省略号位置:在某些编译器中,省略号(
...
)在宏定义中的位置要求可能不同,有的要求紧跟在最后一个命名参数之后,有的则允许有空格等。 - 空参数处理:当可变参数宏调用时传递空参数列表,不同编译器处理方式可能不同。一些编译器可能会导致编译错误,而另一些可能会有特定的处理规则。
编写可移植代码的方法
- 使用标准宏:利用C99标准引入的
__VA_ARGS__
宏,大多数现代编译器都支持。 - 检查编译器宏:通过
#ifdef
等预处理指令检查当前编译器,针对不同编译器编写特定的代码。
示例
#include <stdio.h>
// 可移植的可变参数宏定义
#ifdef _MSC_VER // Visual Studio编译器
#define LOG(fmt, ...) printf(fmt, __VA_ARGS__)
#else // 其他编译器,如GCC
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#endif
int main() {
int num = 10;
LOG("The number is %d\n", num);
return 0;
}
在上述示例中,通过 #ifdef _MSC_VER
检查是否为Visual Studio编译器。对于Visual Studio,直接使用 __VA_ARGS__
;对于其他编译器(如GCC),使用 ##__VA_ARGS__
,##
用于在可变参数为空时去掉前面的逗号,保证编译通过。这样的代码在不同编译器下具有更好的可移植性。