C和C++标准都很好地定义了无符号整数溢出。例如,C99 standard (§6.2.5/9
)状态
涉及无符号操作数的计算永远不能超过flow,因为不能由产生的无符号整数类型表示的结果将以比结果类型可以表示的最大值大1的数字为模减少。
但是,这两个标准都声明有符号整数溢出是未定义的行为。同样,来自C99标准(§3.4.3/1
)
fioverflow上的integer行为是unde行为的一个示例
有没有历史或者(更好的!)造成这种差异的技术原因是什么?
发布于 2013-08-13 04:10:43
除了Pascal的好答案(我确信这是主要的动机),一些处理器也可能在有符号整数溢出时导致异常,如果编译器必须“安排另一种行为”,这当然会导致问题(例如,使用额外的指令来检查潜在的溢出并在这种情况下以不同的方式计算)。
同样值得注意的是,“未定义的行为”并不意味着“不起作用”。这意味着在这种情况下,允许实现做它喜欢做的任何事情。这包括做“正确的事情”以及“报警”或“撞车”。大多数编译器,在可能的情况下,会选择“做正确的事情”,假设这是相对容易定义的(在这种情况下,它是)。然而,如果你在计算中有溢出,重要的是要了解这实际上导致了什么,编译器可能会做一些不同于你期望的事情(这可能非常依赖于编译器版本,优化设置等)。
发布于 2016-12-22 17:53:33
首先,请注意,与所有示例和脚注一样,C11 3.4.3不是标准文本,因此与引用无关!
声明整数和浮点数溢出是未定义行为的相关文本如下:
C11 6.5/5
如果在表达式求值过程中出现异常条件(即,如果结果不是数学定义的,或者不在其类型的可表示值范围内),则行为是未定义的。
关于无符号整数类型的行为的说明可以在这里找到:
C11 6.2.5/9
有符号整数类型的非负值范围是对应的无符号整数类型的子范围,并且每种类型中相同值的表示形式是相同的。涉及无符号操作数的计算永远不会溢出,因为不能由产生的无符号整数类型表示的结果将以比结果类型可以表示的最大值大1的数字为模减少。
这使得无符号整数类型成为一种特殊情况。
另请注意,如果将任何类型转换为带符号的类型,并且旧值不能再表示,则会出现异常。然后,行为只是由实现定义的,尽管可能会引发一个信号。
C11 6.3.1.3
6.3.1.3有符号和无符号整数当integer类型的值转换为_Bool以外的其他整数类型时,如果该值可以用新类型表示,则保持不变。否则,如果新类型是无符号的,则通过重复添加或减去新类型中可表示的最大值一个以上的值来转换该值,直到该值在新类型的范围内为止。否则,新类型将有符号,并且无法在其中表示值;要么结果是实现定义的,要么引发实现定义的信号。
发布于 2013-08-27 01:32:00
除了提到的其他问题外,使用无符号数学包装可以使无符号整数类型表现为抽象代数组(这意味着,除其他外,对于任何一对值X
和Y
,都会存在一些其他值Z
,这样,如果正确转换,X+Z
将等于Y
,而如果正确转换,Y-Z
将等于X
)。如果无符号值仅仅是存储位置类型,而不是中间表达式类型(例如,如果没有最大整数类型的无符号等价物,并且对无符号类型的算术操作就像它们首先被转换为更大的有符号类型一样,那么就不需要那么多定义的包装行为,但是在没有加法逆的类型中进行计算是困难的。
这在回绕行为实际有用的情况下很有帮助-例如,对于TCP序列号或某些算法,例如散列计算。在有必要检测溢出的情况下,它也可能有所帮助,因为执行计算并检查它们是否溢出通常比预先检查它们是否溢出更容易,特别是在计算涉及最大可用整数类型的情况下。
https://stackoverflow.com/questions/18195715
复制相似问题