C++下溢和上溢

j7dteeu8  于 2024-01-09  发布在  其他
关注(0)|答案(4)|浏览(150)

我试图理解下溢和上溢在C++中是如何工作的。我的理解是,如果一个变量的范围被超过,它将从范围的另一端开始。因此,如果short的最小值是-32768,如果我们从中减去1,新的值应该是SHRT_MAX(32767)。
下面是我的代码:

  1. #include <iostream.h>
  2. #include <limits.h>
  3. #include <conio.h>
  4. int main (void)
  5. {
  6. int testpositive = INT_MIN;
  7. short testnegative = SHRT_MIN;
  8. cout << SHRT_MIN << "\n";
  9. cout << testnegative - 1 << "\n";
  10. cout << INT_MIN << "\n";
  11. cout << testpositive - 1 << "\n";
  12. cout << testpositive - 2;
  13. getch();
  14. return 0;
  15. }

字符串

rqqzpn5f

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来说,有符号值和无符号值之间没有区别(有符号和无符号 * 操作 *,但值本身只是位)。
请注意,编译器可以假设(大多数现代优化编译器实际上都假设)在正确的程序中不会发生有符号整数溢出,例如在这样的代码中:

  1. int do_something();
  2. int do_something_else();
  3. void foo() {
  4. int x = do_something();
  5. int y = x + 1;
  6. if (x < y) {
  7. do_something();
  8. } else {
  9. do_something_else();
  10. }
  11. }

字符串
编译器可以完全跳过测试和生成代码中的else分支,因为在有效程序中,有符号int x总是小于x+1。(因为有符号溢出不能被视为有效行为)。但是,如果将int替换为unsigned int,编译器必须为测试和else分支生成代码,因为对于无符号类型,可能是x > x+1
例如,clang将foo的代码编译为

  1. foo(): # @foo()
  2. push rax
  3. call do_something()
  4. pop rax
  5. jmp do_something() # TAILCALL


在这里你可以看到ode只调用了do_something两次(除了对rax的奇怪处理),实际上没有提到do_something_elsegcc生成的代码或多或少是相同的。

展开查看全部
6ovsh4lw

6ovsh4lw2#

有符号溢出是C++中未定义的行为。
举例来说:
第一个月
-INT_MIN
是调用未定义行为的表达式。
在16位short和32位int的环境中,SHRT_MIN - 1-SHRT_MIN不是未定义的行为,因为使用整数提升时,操作数首先提升为int。在16位shortint的环境中,这些表达式也是未定义的行为。

czfnxgou

czfnxgou3#

通常情况下是的。但是因为这是C++,而C是由C标准规范的,你必须知道溢出是未定义的行为
虽然你所说的可能适用于大多数平台,但这并不能保证,所以不要依赖它。

j9per5c4

j9per5c44#

新值不需要是SHRT_MAX,它是未定义的。

相关问题