为何GCC与MSVC中宏模拟函数默认参数的展开结果不同?
宏模拟函数默认参数的跨编译器行为问题
问题背景
受StackOverflow相关问题启发,我编写了一段C代码,尝试用宏模拟函数默认参数:定义了do_func函数及配套宏,预期通过MACRO_CHOOSER根据传入参数的个数,选择调用FUNC_2_ARGS或FUNC_3_ARGS来实现默认参数效果。这段代码在GCC、Clang中的预处理器展开结果符合预期,但Visual C 19.32始终调用not_func。
我想明确三个问题:
- 依据C/C++标准,哪种编译器的行为是正确的?
- 这种写法是否合法?
- 是否仅在C中合法,在C++中不合法?
解答
标准层面的正确行为:GCC和Clang的行为符合C/C标准,Visual C 19.32的行为不符合标准。这种通过宏参数个数匹配目标宏的技巧,核心是利用预处理器对可变参数宏(
__VA_ARGS__)的展开规则,通过参数列表长度索引到对应宏。标准允许这类基于参数个数的宏重载实现,VC++的问题属于自身预处理器的实现缺陷。写法的合法性:这种写法在C99及后续版本、C11及后续版本中均合法。C99引入了可变参数宏特性,C11也跟进支持,标准并未禁止通过参数计数实现宏重载逻辑,只要宏的定义和展开符合预处理器语法规则,就属于合法写法。
C与C++的兼容性:该写法在C和C中都合法,不存在仅C合法、C不合法的情况。两者在可变参数宏的核心规则上保持一致,这类宏技巧不受C/C++语言特性差异的影响。
内容的提问来源于stack exchange,提问作者yeputons
相关产品推荐
相关产品推荐

