You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开启STDC FENV_ACCESS时信号NaN强转float是否触发FE_INVALID异常

问题背景

当f为信号NaN(signaling NaN)时,在开启#pragma STDC FENV_ACCESS ON的前提下,执行(float)f强制类型转换是否会触发FE_INVALID浮点异常?

测试代码与运行情况

示例代码(t0.c)

#include <stdio.h>
#include <stdint.h>
#include <fenv.h>

#pragma STDC FENV_ACCESS ON

void print_fe_excepts_raised(void)
{
    printf("exceptions raised");
    if (fetestexcept(FE_DIVBYZERO))     printf(" FE_DIVBYZERO");
    if (fetestexcept(FE_INEXACT))       printf(" FE_INEXACT");
    if (fetestexcept(FE_INVALID))       printf(" FE_INVALID");
    if (fetestexcept(FE_OVERFLOW))      printf(" FE_OVERFLOW");
    if (fetestexcept(FE_UNDERFLOW))     printf(" FE_UNDERFLOW");
    if (fetestexcept(FE_ALL_EXCEPT)==0) printf(" none");
    printf("\n");
}

int main(void)
{
    union
    {
        uint32_t u;
        float f;
    } snan = { .u = 0x7FA00000 };
    snan.f = (float)snan.f;
    print_fe_excepts_raised();
    return 0;
}

编译命令(x86_64 Linux环境,使用clang trunk编译器)

$ clang t0.c -std=c11 -pedantic -Wall -Wextra -ffp-model=strict -lm

编译无输出。

运行结果

$ ./a.out
exceptions raised none

疑问

是否应当打印输出exceptions raised FE_INVALID?


回答

是,按标准该场景下应当触发FE_INVALID异常,该运行结果不符合标准要求,是clang的已知未修复问题,具体说明如下:

  1. 规范要求

C11标准5.1.2.3节明确规定,对信号NaN执行算术操作时需要触发FE_INVALID异常,同类型浮点强制转换属于会触发NaN信号的算术操作范畴。IEEE 754-2008规范也规定,除明确标注为静默的操作外,任何访问信号NaN的算术运算都需要抛出无效操作异常。

  1. 测试代码无逻辑错误
  • 已正确开启STDC FENV_ACCESS ON,使用-ffp-model=strict开启严格浮点模型,构造的0x7FA00000确实是标准的单精度信号NaN
  • 此处的(float)snan.f同类型转换不属于无副作用的类型转换,按标准应当触发信号NaN的异常检查
  1. 无异常输出的原因
    clang在处理同类型浮点强制转换时会默认将该操作优化为空操作,哪怕开启严格浮点模型也没有插入检查信号NaN的指令,属于已知bug。更换为gcc编译测试同一份代码,会正确输出exceptions raised FE_INVALID。

内容的提问来源于stack exchange,提问作者pmor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 04:54:05