如何解释C11标准第6.3.1.4节第1段(关于将float转换为unsigned int)

D.J*_*ind 5 c undefined-behavior language-lawyer

我的C11标准来自这里。这一段说:

\n
\n

当实浮点类型的有限值转换为_Bool以外的整数类型时,小数部分将被丢弃(即该值被截断为零)。如果整数部分的值不能用整数类型表示,则行为未定义。[61]

\n
\n

脚注 61 说:

\n
\n

当实浮点类型的值转换为无符号类型时,不需要执行整数类型的值转换为无符号类型时执行的余数运算。因此,可移植实浮点值的范围为(\xe2\x88\x921, U type _MAX +1)

\n
\n

我的困惑主要是关于unsigned int. 我目前的理解如下:

\n
float    a = 3.14;\nuint32_t b = (uint32_t)a; // defined, b == 3\n\nfloat    a = -1.23;\nuint32_t b = (uint32_t)a; // UB!\n\nfloat a = 2147483646.0;   // defined\nuint32_t b = (uint32_t)a; // defined, b == 2147483646\nuint8_t  c = (uint8_t )a;  // UB!\n
Run Code Online (Sandbox Code Playgroud)\n

它是否正确?

\n

nie*_*sen 1

脚注 61 阐明了可以转换为无符号整数类型而没有未定义行为的浮点数的范围。

无符号整数类型可以表示 [0; 范围内的值。Utype_MAX]。因此,在此区间内具有整数部分的任何浮点值都可以转换为无符号整数类型,这意味着值x其中x > -1 and x < Utype_MAX+1。这是脚注61最后部分的陈述。

一般规则是,当对无符号整数进行运算导致数字超出范围 时[0; Utype_MAX],结果将被缩减模块Utype_MAX+1(也称为“环绕”)。例如,当两个 16 位整数相加时,40000+40000=80000(无法用 16 位表示),结果将模 65536 缩小为 14464。

但是,在将浮点数转换为无符号整数时,不需要进行这种环绕操作。这是脚注 61 中的第一个陈述。