提问人:chqrlie 提问时间:10/29/2023 更新时间:11/16/2023 访问量:155
为整数类型分配无限值是否具有未定义的行为?
Does assigning infinite values to integer types have undefined behavior?
问:
C 标准规定了有限浮点值在存储为整数类型时如何转换它们,但它似乎没有指定非有限值的行为:
6.3.1.4 实浮点数和整数
1 当标准浮点型的有限值转换为 以外的整数类型时,小数部分将被丢弃(即,该值被截断为零)。如果整数部分的值不能用整数类型表示,则行为是未定义的。
bool
2 当十进制浮点型的有限值转换为整数类型时,小数部分将被丢弃(即,该值被截断为零)。如果整数部分的值不能用整数类型表示,则应引发“无效”浮点异常,并且未指定转换结果。
bool
3 当整数类型的值转换为标准浮点型时,如果正在转换的值可以精确地用新类型表示,则该值保持不变。如果要转换的值在可以表示但不能精确表示的值范围内,则结果是以实现定义的方式选择的最接近的较高或最接近的较低可表示值。如果要转换的值超出了可以表示的值范围,则行为未定义。某些隐式转换的结果可能以比新类型所需的范围和精度更大的范围和精度表示(见6.3.1.8和6.8.6.4)。
4 当整数类型的值转换为十进制浮点型时,如果转换的值可以准确地用新类型表示,则该值保持不变。如果无法准确表示要转换的值,则应正确舍入结果,并按照 IEC 60559 的规定引发异常。
行为是在 C 标准的其他位置指定还是未定义?
答:
将浮点类型的无限值转换为整数类型是未定义的 C,不是因为标准说了什么,而是因为它没有说什么。
该行为是否在 C 标准的其他部分未定义?
该标准不需要显式声明行为为“未定义”,即可将其定义为未定义。简单地不定义它就足够了。这是对未定义行为的定义。引用 N3096/3.4.3,
3.4.3
使用不可移植或错误的程序结构或错误数据时未定义的行为
行为,本文档对此没有要求
注意:正如 Eric Postpischil 的回答中提到的,该标准还指出,明确标明“未定义”的行为与省略任何定义的行为之间没有区别。两者都是同样未定义的行为。
该标准仅对浮点类型的有限值转换为整数类型提出了要求。标准未涵盖的每个情况,当然都是未定义的行为。
为了获得额外的保证,附录 J.2(未定义的行为)下有以下条目:
在以下情况下,该行为未定义:
...
(16) 与整数类型之间的转换会产生一个超出可表示范围的值 (6.3.1.4)。
由于无穷大确实超出了整数类型可以表示的范围,因此将无穷大转换为整数类型是未定义的。
评论
C 2018 4 2 说:
如果违反了出现在约束或运行时约束之外的“应”或“不应”要求,则该行为未定义。在本文档中,未定义的行为以“未定义的行为”一词或省略任何明确的行为定义来表示。这三者在侧重点上没有区别;它们都描述了“未定义的行为”。
由于没有明确定义将无限值转换为整数类型的行为,因此它是未定义的行为。
C17 6.3.1.4 §1 有点解决了这个问题,因为它明确地谈到了有限浮点值是有效的转换,这意味着无限浮点值不是:
当实数浮点类型的有限值转换为 以外的整数类型时,小数部分将被丢弃(即,该值被截断为零)。如果整数部分的值不能用整数类型表示,则行为是未定义的。
_Bool
我相信人们也可以说,这包含在“捕获所有”规则中,该规则也是处理有符号整数溢出的规则,C17 6.5 §5:
如果在计算表达式期间发生异常情况(即,如果结果不是 在数学上定义或不在其类型的可表示值范围内),该行为是 定义。
评论
trunc