Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么定义了无符号整数溢出行为,但有符号整数溢出不是';T 无符号整数溢出是由C和C++标准定义的。例如,(§6.2.5/9)规定_C++_C_Undefined Behavior_Integer Overflow - Fatal编程技术网

为什么定义了无符号整数溢出行为,但有符号整数溢出不是';T 无符号整数溢出是由C和C++标准定义的。例如,(§6.2.5/9)规定

为什么定义了无符号整数溢出行为,但有符号整数溢出不是';T 无符号整数溢出是由C和C++标准定义的。例如,(§6.2.5/9)规定,c++,c,undefined-behavior,integer-overflow,C++,C,Undefined Behavior,Integer Overflow,涉及无符号操作数的计算永远不会溢出, 因为无法由结果无符号整数类型表示的结果是 约化模:比可计算的最大值大一的数 由结果类型表示 但是,这两个标准都声明有符号整数溢出是未定义的行为。同样,来自C99标准(§3.4.3/1) 未定义行为的一个例子是整数过流的行为 这种差异是历史原因还是(甚至更好!)技术原因?历史原因是大多数C实现(编译器)只使用最容易用整数表示实现的溢出行为。C实现通常使用CPU使用的相同表示法-因此溢出行为遵循CPU使用的整数表示法 在实践中,只有符号值的表示可能因实现不同而有

涉及无符号操作数的计算永远不会溢出, 因为无法由结果无符号整数类型表示的结果是 约化模:比可计算的最大值大一的数 由结果类型表示

但是,这两个标准都声明有符号整数溢出是未定义的行为。同样,来自C99标准(
§3.4.3/1

未定义行为的一个例子是整数过流的行为


这种差异是历史原因还是(甚至更好!)技术原因?

历史原因是大多数C实现(编译器)只使用最容易用整数表示实现的溢出行为。C实现通常使用CPU使用的相同表示法-因此溢出行为遵循CPU使用的整数表示法

在实践中,只有符号值的表示可能因实现不同而有所不同:一的补码、二的补码、符号大小。对于无符号类型,标准没有理由允许变化,因为只有一种明显的二进制表示(标准只允许二进制表示)

相关引用:

C99 6.2.6.1:3

存储在无符号位字段和无符号字符类型的对象中的值应使用纯二进制表示法表示

C99 6.2.6.2:2

如果符号位为1,则应通过以下方式之一修改该值:

-符号位为0的对应值为负数(符号和幅值)

-符号位具有该值−(2N)(二的补语)

-符号位具有该值−(2N− 1) (补语)



现在,所有处理器都使用2的补码表示,但有符号算术溢出仍然没有定义,编译器制造商希望它保持未定义,因为他们使用这种未定义来帮助优化。例如,请参阅Ian Lance Taylor的这篇文章或Agner Fog的这篇文章,以及他的错误报告的答案。

除了Pascal的好答案(我确信这是主要动机)之外,还可能有一些处理器导致有符号整数溢出异常,如果编译器不得不这样做,这当然会导致问题“安排其他行为”(例如,使用额外说明检查潜在溢出,并在这种情况下进行不同的计算)


还值得注意的是,“未定义的行为”并不意味着“不起作用”。它意味着允许实现在这种情况下做它想做的任何事情。这包括做“正确的事情”以及“报警”或“崩溃”。如果可能,大多数编译程序都会选择“做正确的事情”,假设这相对容易定义(在本例中是)。但是,如果计算中出现溢出,了解实际结果很重要,编译器可能会执行与预期不同的操作(这可能很大程度上取决于编译器版本、优化设置等)

除了上面提到的其他问题外,使用无符号数学换行符会使无符号整数类型表现为抽象代数组(这意味着,除其他外,对于任何一对值
X
Y
,都将存在一些其他值
Z
,使得
X+Z
如果正确投射,将等于
Y
Y-Z
如果正确投射,将等于
X
)。如果无符号值只是存储位置类型而不是中间表达式类型(例如,如果没有最大整数类型的无符号等价物,并且无符号类型上的算术运算的行为就好像它们第一次被转换为更大的有符号类型一样,那么就不需要定义包装行为,但在没有加法求逆的类型中进行计算是很困难的


这在环绕行为实际有用的情况下会有所帮助,例如TCP序列号或某些算法,如哈希计算。在需要检测溢出的情况下也会有所帮助,因为执行计算和检查它们是否溢出通常比事先检查r它们会溢出,尤其是当计算涉及最大的可用整数类型时。

首先,请注意,C11 3.4.3与所有示例和脚注一样,不是规范性文本,因此与引用无关

声明整数和浮点溢出是未定义行为的相关文本如下:

C116.5/5

如果在评估过程中出现异常情况 表达式(即,如果结果不是数学定义的,或 不在其类型的可表示值范围内),行为 没有定义

有关无符号整数类型行为的详细说明,请参见:

C116.2.5/9

有符号整数类型的非负值范围是一个子范围 对应的无符号整数类型的 每种类型中的相同值都是相同的 无符号操作数永远不会溢出,因为结果 由此产生的无符号整数类型表示为约化模 比可以使用的最大值大一的数字 由结果类型表示

这使得无符号整数类型成为一种特殊情况

还请注意,如果任何类型转换为有符号类型,并且旧值可以