FLT_HAS_SUBNORM 是 0:在使用这种次正规时,手动构造的次正规会导致明确定义的行为吗?

FLT_HAS_SUBNORM is 0: does manually constructed subnormal lead to well-defined behavior when using such subnormal?

如果 FLT_HAS_SUBNORM 为 0:是否手动构建(例如,通过 union 或使用 memcpy() 使用双关语)次常态会导致明确定义的行为subnormal 用作 FP 操作(例如 FP 比较)的输入?

示例:

#include <stdio.h>
#include <float.h>
int main( void )
{
    union { unsigned int i; float f; } u = { .i = 1 }; // subnormal
    printf("%d %d %a 0x%08lx\n", FLT_HAS_SUBNORM, u.f != 0.0f, u.f, u.i);
    return 0;
}

输出:

叮当声:1 1 0x1p-149 0x00000001

gcc: 1 1 0x1p-149 0x00000001

测试编译器:0 1 0x0p+0 0x00000001

注意:这里我们看到测试编译器不支持次正规的 %a(这由 / 与 FLT_HAS_SUBNORM 相关解释为 0)。

问题:

  1. 这里的 u.f != 0 会导致定义明确的行为吗?
  2. 如果是这样,那么如果 FLT_HAS_SUBNORM 为 0,那么为什么 C 标准允许此类手动构造的次正规(以及具有此类手动构造的次正规的 FP 操作导致符合 IEEE 754 的结果)?

更新。我读过标准。我很困惑,因为它说:

FLT_HAS_SUBNORM is 0 means that subnormal numbers are absent (type does not support subnormal numbers)

然而,尽管在上面的示例中有 type does not support subnormal numbers,我们已经看到可以手动构造次正规并对其执行一些 FP 操作以获得符合 IEEE 754 的结果。

更新。换句话说:上面的例子(u.f != 0.0f)应该被解释为违反FLT_HAS_SUBNORM is 0吗?如果是,请证明。

Is u.f != 0 here leads to well-defined behavior?

没有。如果不支持次正规数,那么无论它们是如何获得的,无论是通过源代码中的文字、算术,还是对表示浮点对象的位的操作,都不支持它们。

If so, then why C standard permits such manually constructed subnormals…

C 是一种低级语言,允许直接访问表示任何对象的字节。您还可以构造由于奇偶校验错误(在具有此类错误的实现上)而无效的整数表示以及不在定义字符集中的 char 对象的表示。您还可以修改 FILEstruct tm 的字节并生成具有不受支持的值的对象。您可以操纵字节这一事实并不意味着对字节的任何操纵都会产生有效或受支持的值。