有符号整数溢出在 C++ 中仍然是未定义的行为吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16188263/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is signed integer overflow still undefined behavior in C++?
提问by Archie
As we know, signed integer overflow is undefined behavior. But there is something interesting in C++11 cstdint
documentation:
众所周知,有符号整数溢出是未定义行为。但是在 C++11cstdint
文档中有一些有趣的东西:
signed integer type with width of exactly 8, 16, 32 and 64 bits respectively with no padding bits and using 2's complement for negative values(provided only if the implementation directly supports the type)
宽度分别为 8、16、32 和 64 位的有符号整数类型,没有填充位,对负值使用 2 的补码(仅当实现直接支持该类型时才提供)
And here is my question: since the standard says explicitly that for int8_t
, int16_t
, int32_t
and int64_t
negative numbers are 2's complement, is still overflow of these types an undefined behavior?
这里是我的问题:由于标准明确地说,对int8_t
,int16_t
,int32_t
和int64_t
负数是2的补,还是溢出这些类型的未定义的行为吗?
EditI checked C++11 and C11 Standards and here is what I found:
编辑我检查了 C++11 和 C11 标准,这是我发现的:
C++11, §18.4.1:
C++11,第 18.4.1 节:
The header defines all functions, types, and macros the same as 7.20 in the C standard.
头文件定义了与 C 标准中的 7.20 相同的所有函数、类型和宏。
C11, §7.20.1.1:
C11,第 7.20.1.1 节:
The typedef name
intN_t
designates a signed integer type with width N, no padding bits, and a two's complement representation. Thus,int8_t
denotes such a signed integer type with a width of exactly 8 bits.
typedef 名称
intN_t
指定宽度为 N、无填充位和二进制补码表示的有符号整数类型。因此,int8_t
表示具有恰好 8 位宽度的这种有符号整数类型。
采纳答案by Andy Prowl
is still overflow of these types an undefined behavior?
这些类型的溢出仍然是未定义的行为吗?
Yes.Per Paragraph 5/4 of the C++11 Standard (regarding any expression in general):
是的。根据 C++11 标准的第 5/4 段(关于一般的任何表达式):
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined. [...]
如果在对表达式求值期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为为 undefined。[...]
The fact that a two's complement representation is used for those signed types does not mean that arithmetic modulo 2^n is used when evaluating expressions of those types.
对那些有符号类型使用二进制补码表示的事实并不意味着在评估这些类型的表达式时使用算术模 2^n。
Concerning unsignedarithmetic, on the other hand, the Standard explicitly specifies that (Paragraph 3.9.1/4):
另一方面,关于无符号算术,标准明确规定(第 3.9.1/4 段):
Unsigned integers, declared
unsigned
, shall obey the laws of arithmetic modulo 2^nwhere n is the number of bits in the value representation of that particular size of integer
无符号整数,声明
unsigned
,应当服从算术模的法律2 ^ N,其中n是比特的整数的特定大小的值表示的数目
This means that the result of an unsigned arithmetic operation is always "mathematically defined", and the result is always within the representable range; therefore, 5/4 does not apply. Footnote 46 explains this:
这意味着无符号算术运算的结果总是“数学定义的”,并且结果总是在可表示的范围内;因此,5/4 不适用。脚注 46 解释了这一点:
46) This implies that unsignedarithmetic does not overflow because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer type.
46) 这意味着无符号算术不会溢出,因为无法由结果无符号整数类型表示的结果以比结果无符号整数类型可以表示的最大值大一的数为模减少。
回答by ecatmur
Just because a type is defined to use 2s complement representation, it doesn't follow that arithmetic overflow in that type becomes defined.
仅仅因为一个类型被定义为使用 2s 补码表示,它并不遵循该类型中的算术溢出被定义。
The undefined behaviour of signed arithmetic overflow is used to enable optimisations; for example, the compiler can assume that if a > b
then a + 1 > b
also; this doesn't hold in unsigned arithmetic where the second check would need to be carried out because of the possibility that a + 1
might wrap around to 0
. Also, some platforms can generate a trap signal on arithmetic overflow (see e.g. http://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html); the standard continues to allow this to occur.
有符号算术溢出的未定义行为用于启用优化;例如,编译器可以假设 if a > b
then a + 1 > b
also; 这在无符号算术中不成立,因为可能a + 1
会环绕到,因此需要进行第二次检查0
。此外,某些平台可以在算术溢出时生成陷阱信号(参见例如http://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html);该标准继续允许这种情况发生。
回答by EnzoR
I would bet so.
我敢打赌。
From the standard documentation (pg.4 and 5):
来自标准文档(第 4 和 5 页):
1.3.24 undefined behavior
behavior for which this International Standard imposes no requirements
[ Note: Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed.-- end note]
1.3.24 未定义行为
本国际标准没有要求的行为
[注意:当本国际标准省略任何明确的行为定义或程序使用错误的构造或错误的数据时,可能会出现未定义的行为。允许的未定义行为范围从完全忽略情况并产生不可预测的结果,在翻译或程序执行期间以环境特征的文件化方式(有或没有发布诊断消息),到终止翻译或执行(通过发布诊断消息)。许多错误的程序结构不会产生未定义的行为;他们需要被诊断出来。--尾注]