cl:编译时间与运行时间:inf与-nanind

问题描述

示例代码t50.c):

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <math.h>
#include <float.h>
#include <assert.h>

const float d1 = NAN;
const float d2 = -0x0p+0;
const float d3 = NAN / -0x0p+0;

typedef union { uint32_t u; float d; } u_t;

int main(void)
{
        u_t u1;
        u_t u2;
        u_t u3;

        u1.d = *(volatile float*)&d1 / *(volatile float*)&d2;
        u2.d = d3;
        u3.d = d1 / d2;
        if ( u1.u != u2.u || u1.u != u3.u )
        {
                printf("error:\n");
                printf("u1 (run time)     %08"PRIx32" %.*e\n",u1.u,DECIMAL_DIG,u1.d);
                printf("u2 (compile time) %08"PRIx32" %.*e\n",u2.u,u2.d);
                printf("u3                %08"PRIx32" %.*e\n",u3.u,u3.d);
        }
        return 0;
}

编译器调用cl t50.c /O1 /fp:precise && t50

预期结果:<nothing>

实际结果(与cl x86cl x64相同):

error:
u1 (run time)     ffc00000 -nan(ind)
u2 (compile time) 7f800000 inf
u3                ffc00000 -nan(ind)

我指定了/fp:strictcl t50.c /O1 /fp:strict && t50,但得到了:

t50.c(8): error C2099: initializer is not a constant
t50.c(10): error C2099: initializer is not a constant

cl版本:19.25.28611 for x8619.25.28611 for x64

gcc(10.2.0)和clang(11.0.0)比较:

gcc t50.c -O2 && a.exe
<nothing>

clang t50.c -O2 && a.exe
<nothing>

为什么?我在这里想念的是什么? 标准(C / IEEE)怎么说?

UPD1:

  1. if ( u1.d != u2.d || u1.d != u3.d )的结果相同。
  2. 相同的结果w/o unions(即使用float u1,u2,u3)。

UPD2:

  1. 编译器的NAN定义:Windows Kits\10\Include\10.0.18362.0\ucrt\corecrt_math.h#define NAN ((float)(INFINITY * 0.0F))
  2. u1.d = NAN; printf("NAN %08"PRIx32" %.*e\n",u1.d);(对于cl x86cl x64输出):NAN ffc00000 -nan(ind)

解决方法

为什么?

cl不遵循IEEE-754关于NAN

我在这里缺少什么?

假定遵循IEEE的C编译器。

标准C怎么说?

C在NAN部门中对规范不严谨。我认为编译器是合规的,只是涉及NAN的实现质量较差。

IEEE的标准是什么?

不符合规定。