You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C99中0.0/0.0的写法是否合法?MSVC对其的差异化编译是否符合标准?

C99中0.0/0.0的写法是否合法?MSVC对其的差异化编译是否符合标准?

咱们先把这个问题拆成两部分来看:首先是0.0/0.0在C99标准里的合法性,然后再分析MSVC那看起来矛盾的编译行为到底合不合规。

首先说标准层面的规则:

  • 在C99的核心标准里,并没有强制要求编译器支持IEEE 754的NaN(非数)这类浮点特性,整数除以零是明确的未定义行为,但浮点数的0除以0,核心标准只说其结果由实现定义。
  • 但如果编译器实现了C99的Annex F(IEC 60559浮点算术支持)——也就是咱们常说的IEEE 754兼容——那标准明确要求0.0/0.0的结果是NaN,既不能触发编译错误,也不能在运行时抛出异常,而是要生成合法的NaN值。

接下来看MSVC的奇怪行为:
你遇到的两种情况,本质是MSVC对编译期求值运行时求值的处理不一致:

  1. 0.0/0.0出现在函数内的自动变量初始化时,MSVC会尝试把这个表达式当作编译期常量来计算,但它的编译期浮点处理逻辑并没有遵循IEEE 754的规则,反而直接把0除以0判定为错误,抛出C2124
  2. 0.0/0.0用来初始化全局变量时,MSVC没有在编译期强制求值,而是把这个计算延迟到了程序启动阶段(运行时),而它的运行时浮点环境是遵循IEEE 754的,所以能正常生成NaN,不会报错。

反观GCC和Clang,它们不管是编译期还是运行时处理浮点常量表达式,都严格遵循IEEE 754规则,所以两种情况都能正常编译,直接生成NaN常量。

那MSVC的行为到底合规吗?
既然MSVC官方声称支持IEEE 754,那它就应该遵守C99 Annex F的要求。从这个角度看,它在函数内拒绝0.0/0.0的做法是不符合标准的——因为Annex F要求这类运算必须生成NaN,而不是触发编译错误。不过这里也有个灰色地带:C标准对编译期浮点常量表达式的求值规则,没有完全明确要求必须遵循Annex F,但既然编译器宣称支持IEEE 754,就应该在所有场景下保持一致。

最后回到你的实际需求:如果是为了替代MSVC里不被当作常量的NAN宏,用全局变量里的0.0/0.0是可行的,但函数内的写法暂时行不通。如果要在函数内生成NaN,可能得换用其他方式,比如调用nan("")这类标准库函数(不过要注意它是不是常量表达式)。

备注:内容来源于stack exchange,提问作者Szabolcs

火山引擎 最新活动