[英]C++ underflow and overflow
您好,我是新来的,所以如果有任何问题请告诉我,下次我会努力改进。
我试图了解下溢和上溢在 C++ 中的工作原理。我的理解是,如果超出变量的范围,它将从范围的另一端开始。 因此,如果 short 的最小值是 -32768,并且如果我们对其执行 -1,则新值应该是 SHRT_MAX。(32767) 这是我的代码:
#include<iostream.h>
#include<limits.h>
#include<conio.h>
int main ( void )
{
int testpositive =INT_MIN ;
short testnegative = SHRT_MIN ;
cout<< SHRT_MIN<<"\n";
cout << testnegative-1<<"\n";
cout << INT_MIN << "\n";
cout << testpositive-1 << "\n";
cout<<testpositive-2;
getch();
return 0;
}
上溢/下溢的确切行为仅针对unsigned
类型指定。
无符号整数应遵守算术模 2^n 的法则,其中 n 是 integer 的特定大小的值表示中的位数。
资料来源: N3690 草案 §3.9.1 第 4 句
这意味着无符号算术不会溢出,因为无法由生成的无符号 integer 类型表示的结果以比生成的无符号 integer 类型可以表示的最大值大 1 的数为模进行缩减。
对于正常签名的 integer 类型,C++ 标准只是简单地说明任何事情都可能发生。
如果在计算表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义
资料来源: N3690 草案§5 第 4 句
如果我们谈论的是 x86 处理器(或大多数其他现代处理器),那么行为正是您所描述的,对于 CPU,有符号值或无符号值之间没有区别(有符号和无符号操作,但值它们本身只是位)。
请注意,编译器可以假设(并且大多数现代优化编译器实际上都假设)在正确的程序中不会发生带符号的 integer 溢出,例如在如下代码中:
int do_something();
int do_something_else();
void foo() {
int x = do_something();
int y = x + 1;
if (x < y) {
do_something();
} else {
do_something_else();
}
}
编译器可以完全跳过生成代码中的测试和else
分支,因为在有效程序中,带符号的 int x
总是小于x+1
(因为带符号溢出不能被视为有效行为)。 但是,如果您将int
替换为unsigned int
,编译器必须为测试和 else 分支生成代码,因为对于无符号类型, x > x+1
是可能的。
例如 clang 将foo
的代码编译为
foo(): # @foo()
push rax
call do_something()
pop rax
jmp do_something() # TAILCALL
在那里你可以看到颂歌只调用了do_something
两次(除了对rax
的奇怪处理)并且实际上没有提到do_something_else
。 gcc
生成的代码大致相同。
有符号溢出是 C++ 中的未定义行为。
例如:
INT_MIN - 1
-INT_MIN
是调用未定义行为的表达式。
SHRT_MIN - 1
和-SHRT_MIN
在具有 16 位short
和 32 位int
的环境中不是未定义的行为,因为通过 integer 提升操作数首先提升为int
。 在 16 位short
和int
的环境中,这些表达式也是未定义的行为。
通常是的。 但是既然这是C++,而C++是C++标准规定的,要知道溢出是未定义的行为。
尽管您所说的内容可能适用于大多数平台,但无法保证,所以不要依赖它。
新值不必是SHRT_MAX
它是未定义的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.