我试图理解下溢和上溢在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;
}
字符串
4条答案
按热度按时间rqqzpn5f1#
上溢/下溢的确切行为仅针对
unsigned
类型指定。无符号整数应遵守算术模2^n定律,其中n是该特定大小的整数的值表示中的位数。
来源:Draft N3690 §3.9.1 sentence 4
这意味着无符号算术不会溢出,因为无法由结果无符号整数类型表示的结果以比结果无符号整数类型可以表示的最大值大1的数字为模进行缩减。
来源:Draft N3690 Note 47 for §3.9.1
对于普通的有符号整数类型,C++标准只是说任何事情都可能发生。
如果在表达式的计算过程中,结果没有数学定义或不在其类型的可表示值范围内,则行为未定义
来源:Draft N3690 §5 sentence 4
如果我们谈论的是x86处理器(或大多数其他现代处理器),实际上行为正是你所描述的,对于CPU来说,有符号值和无符号值之间没有区别(有符号和无符号 * 操作 *,但值本身只是位)。
请注意,编译器可以假设(大多数现代优化编译器实际上都假设)在正确的程序中不会发生有符号整数溢出,例如在这样的代码中:
字符串
编译器可以完全跳过测试和生成代码中的
else
分支,因为在有效程序中,有符号intx
总是小于x+1
。(因为有符号溢出不能被视为有效行为)。但是,如果将int
替换为unsigned int
,编译器必须为测试和else分支生成代码,因为对于无符号类型,可能是x > x+1
。例如,clang将
foo
的代码编译为型
在这里你可以看到ode只调用了
do_something
两次(除了对rax
的奇怪处理),实际上没有提到do_something_else
。gcc
生成的代码或多或少是相同的。6ovsh4lw2#
有符号溢出是C++中未定义的行为。
举例来说:
第一个月
-INT_MIN
个是调用未定义行为的表达式。
在16位
short
和32位int
的环境中,SHRT_MIN - 1
和-SHRT_MIN
不是未定义的行为,因为使用整数提升时,操作数首先提升为int
。在16位short
和int
的环境中,这些表达式也是未定义的行为。czfnxgou3#
通常情况下是的。但是因为这是C++,而C是由C标准规范的,你必须知道溢出是未定义的行为。
虽然你所说的可能适用于大多数平台,但这并不能保证,所以不要依赖它。
j9per5c44#
新值不需要是
SHRT_MAX
,它是未定义的。