How to interpret paragraph 1 of section 6.3.1.4 of C11 standard (about converting float to unsigned int)

问题描述 投票:0回答:2

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

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

和脚注 61 说:

实型浮点型值转无符号型时,整型值转无符号型时的取余运算不需要。因此,便携式实际浮点值的范围是 (−1, U type _MAX+1)

我的困惑主要是关于

unsigned int
。我目前的理解如下:

float    a = 3.14;
uint32_t b = (uint32_t)a; // defined, b == 3

float    a = -1.23;
uint32_t b = (uint32_t)a; // UB!

float a = 2147483646.0;   // defined
uint32_t b = (uint32_t)a; // defined, b == 2147483646
uint8_t  c = (uint8_t )a;  // UB!

这是正确的吗?

c language-lawyer undefined-behavior
2个回答
0
投票

脚注 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 中的第一个声明。


0
投票

范围说明符

(−1, U_type_MAX+1)
exclusive进一步阅读)。也就是说,指定的端点 not 范围本身的一部分。因此,这意味着可以由给定 unsigned 类型表示的浮点数的
inclusive
范围的下限是
-1
之后的下一个接近零的浮点数(对于 IEEE-754
-0.999999940395
,这将类似于
float
)。同样,上限将是
U_type_MAX+1
之前的下一个较低的可表示值(将被截断为
U_type_MAX
)。

看你的例子:

  1. 3.14
    将被截断为
    3
    – 可以清楚地表示为
    uint32_t
    .
  2. -1.23
    将被截断为
    -1
    – 这不能用 any 无符号类型表示,因此转换是未定义的行为。
  3. uint32_t
    的最大可表示值是
    4294967295
    ,因此您的
    2147483646
    的试验值完全可以很好地定义为转换为该类型;但是,
    uint8_t
    的最大值是
    255
    ,因此转换为该类型是未定义的行为。

再举一个例子,从

-0.999999940395
uint32_t
的转换将被明确定义,因为该值将首先被截断,产生零,它可以用任何无符号类型表示。

© www.soinside.com 2019 - 2024. All rights reserved.