繁体   English   中英

C++ 下溢和上溢

[英]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 的数为模进行缩减。

来源: N3690 草案注释 47 的 §3.9.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 位shortint的环境中,这些表达式也是未定义的行为。

通常是的。 但是既然这是C++,而C++是C++标准规定的,要知道溢出是未定义的行为

尽管您所说的内容可能适用于大多数平台,但无法保证,所以不要依赖它。

新值不必是SHRT_MAX它是未定义的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM