C 下溢和上溢

新手上路,请多包涵

嗨,我是新来的,所以如果有什么问题请告诉我,下次我会努力做得更好。

我试图了解下溢和上溢在 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;
}

原文由 Knownow 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 330
1 个回答

上溢/下溢的确切行为仅针对 unsigned 类型指定。

无符号整数应遵守算术模 2^n 的定律,其中 n 是该特定整数大小的值表示中的位数。

来源: 草案 N3690 §3.9.1 第 4 句

这意味着无符号算术不会溢出,因为不能由得到的无符号整数类型表示的结果以比得到的无符号整数类型可以表示的最大值大一的数字为模减少。

资料来源: N3690 草案第 3.9.1 条注释 47

对于普通的有符号整数类型,C++ 标准只是简单地说,任何事情都可能发生。

如果在计算表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义

资料来源: 草案 N3690 §5 第 4 句

如果我们谈论的是 x86 处理器(或大多数其他现代处理器),那么行为确实正是您所描述的,对于 CPU,有符号值或无符号值之间没有区别(有有符号和无符号 _操作_,但值本身只是位)。

请注意,编译器可以假设(并且大多数现代优化编译器实际上确实假设)在正确的程序中不会发生有符号整数溢出,例如在如下代码中:

 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 分支完全是因为在有效程序中,有符号整数 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

您可以在其中看到 ode 只调用了 do_something 两次(除了对 rax 的奇怪处理)并且实际上没有提及 do_something_else 。或多或少相同的代码由 gcc 生成。

原文由 6502 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏