为整数类型分配无限值是否具有未定义的行为?

Does assigning infinite values to integer types have undefined behavior?

提问人:chqrlie 提问时间:10/29/2023 更新时间:11/16/2023 访问量:155

问:

C 标准规定了有限浮点值在存储为整数类型时如何转换它们,但它似乎没有指定非有限值的行为:

6.3.1.4 实浮点数和整数

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

2 当十进制浮点型的有限值转换为整数类型时,小数部分将被丢弃(即,该值被截断为零)。如果整数部分的值不能用整数类型表示,则应引发“无效”浮点异常,并且未指定转换结果。bool

3 当整数类型的值转换为标准浮点型时,如果正在转换的值可以精确地用新类型表示,则该值保持不变。如果要转换的值在可以表示但不能精确表示的值范围内,则结果是以实现定义的方式选择的最接近的较高或最接近的较低可表示值。如果要转换的值超出了可以表示的值范围,则行为未定义。某些隐式转换的结果可能以比新类型所需的范围和精度更大的范围和精度表示(见6.3.1.8和6.8.6.4)。

4 当整数类型的值转换为十进制浮点型时,如果转换的值可以准确地用新类型表示,则该值保持不变。如果无法准确表示要转换的值,则应正确舍入结果,并按照 IEC 60559 的规定引发异常。

行为是在 C 标准的其他位置指定还是未定义?

c 浮点 类型转换 语言律师 未定义行为

评论

0赞 Brian61354270 10/30/2023
相应的 C++ 问题:无穷大转换为整数是未定义的吗?
0赞 chqrlie 10/30/2023
@Brian61354270:是的,这个问题C++具体,公认的答案指的是函数的 C 规范,这是对 4.10 的延伸解释。C标准的当前语言更加精确,仅与有限值有关。trunc

答:

7赞 Brian61354270 10/30/2023 #1

将浮点类型的无限值转换为整数类型是未定义的 C,不是因为标准了什么,而是因为它没有说什么

该行为是否在 C 标准的其他部分未定义?

该标准不需要显式声明行为为“未定义”,即可将其定义为未定义。简单地不定义它就足够了。这是对未定义行为的定义。引用 N3096/3.4.3

3.4.3
使用不可移植或错误的程序结构或错误数据时未定义的行为
行为,本文档对此没有要求

注意:正如 Eric Postpischil 的回答中提到的,该标准还指出,明确标明“未定义”的行为与省略任何定义的行为之间没有区别。两者都是同样未定义的行为。

该标准仅对浮点类型的有限值转换为整数类型提出了要求。标准未涵盖的每个情况,当然都是未定义的行为。

为了获得额外的保证,附录 J.2(未定义的行为)下有以下条目:

在以下情况下,该行为未定义:
...
(16) 与整数类型之间的转换会产生一个超出可表示范围的值 (6.3.1.4)。

由于无穷大确实超出了整数类型可以表示的范围,因此将无穷大转换为整数类型是未定义的。

评论

1赞 chqrlie 10/30/2023
好吧,我会买的。因此,答案与第一部分相关。不需要额外的保证,也不适用,因为没有定义无限值的转换。
1赞 supercat 10/30/2023
@chqrlie:在编写标准时,一些浮点实现在尝试转换超出范围的值时陷入困境。为了允许浮点到整数转换与其他不相关的操作交错进行,而不承认这种转换可能陷入困境的实现和永远不会陷入困境的实现之间的区别,该标准有必要放弃对所有此类转换的影响的管辖权,前提是以任何方式处理此类转换的实现对其程序员客户最有用。
1赞 supercat 10/30/2023
@chqrlie:许多人滥用该标准声称它禁止其放弃管辖权的构造,而这种放弃管辖权意味着该标准的作者没有努力考虑哪些极端情况应该由声称适合各种目的的实现进行有用的处理。
1赞 supercat 10/30/2023
@chqrlie:已发表的 Rationale 指出,除其他事项外,将动作描述为 UB 允许实现通过指定它们在标准放弃管辖权的情况下的行为方式来扩展语言的语义。作者认识到,许多不同的实现会以不同的方式处理许多结构,并且不想扰乱现状。他们想要禁止所有此类行为的想法与该标准的作者在宪章和理由文件中所写的内容直接矛盾。
2赞 supercat 10/30/2023
@chqrlie:与神话相反,该标准明确指出,指定一个动作调用UB,完全忽略指定其行为,或指定该动作不遵守的约束,在强调上没有区别。如果没有任何内容可以解释为指定行为,则无需明确说明操作调用 UB。
5赞 Eric Postpischil 10/30/2023 #2

C 2018 4 2 说:

如果违反了出现在约束或运行时约束之外的“应”或“不应”要求,则该行为未定义。在本文档中,未定义的行为以“未定义的行为”一词或省略任何明确的行为定义来表示。这三者在侧重点上没有区别;它们都描述了“未定义的行为”。

由于没有明确定义将无限值转换为整数类型的行为,因此它是未定义的行为。

0赞 Lundin 10/30/2023 #3

C17 6.3.1.4 §1 有点解决了这个问题,因为它明确地谈到了有限浮点值是有效的转换,这意味着无限浮点值不是:

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

我相信人们也可以说,这包含在“捕获所有”规则中,该规则也是处理有符号整数溢出的规则,C17 6.5 §5:

如果在计算表达式期间发生异常情况(即,如果结果不是 在数学上定义或不在其类型的可表示值范围内),该行为是 定义。