MSVC开启/O2优化时编译函数指针数组报Initializer is not a constant错误
问题描述
开启/O2优化编译以下C代码时,编译失败并抛出"initialiser is not a constant"错误,仅floor和ceil函数会触发该问题;将代码放在CPP文件中可正常编译,使用/O1优化或关闭优化时也无错误。使用环境为Visual Studio 17.7.6版本,Windows SDK版本为10.0(最新安装版),疑问是MSVC编译器存在bug还是自身操作有误?
代码示例:
#include <math.h> double myfunc(double arg) { return 5.4; }; double (*f[])(double) = { myfunc, fabs, // floor, // THESE TWO TRIGGER THE ERROR // ceil, // initialiser is not a constant sqrt };
问题分析与解答
- 这不是你的操作问题,是MSVC在C语言模式下结合
/O2优化时的特定兼容性问题。 - 核心原因:MSVC在C编译模式、
/O2优化级别下,会把floor和ceil定义为宏而非函数。而C语言规定全局数组的初始化必须使用常量表达式,宏展开后的内容无法作为合法的常量函数指针来初始化数组,因此触发报错。而fabs、sqrt等函数在该优化级别下仍保持函数身份,所以不会出问题。 - 可行解决办法:
- 方法1:在包含
math.h前添加#define _USE_MATH_DEFINES,或者在包含math.h后添加#undef floor、#undef ceil,强制编译器将这两个标识符视为函数而非宏。 - 方法2:如果对性能要求不高,改用
/O1优化或直接关闭优化编译C代码。 - 方法3:将代码后缀改为
.cpp,以C模式编译。C对初始化表达式的规则更宽松,且MSVC在C++模式下不会将这两个函数定义为宏。
- 方法1:在包含
内容的提问来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

