6

こんにちは 私はここに来たばかりなので、何か問題があれば教えてください。次回はもっと良くなるように努めます。

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

4 に答える 4

11

オーバーフロー/アンダーフローの正確な動作は、型に対してのみ指定されていunsignedます。

符号なし整数は、2^n を法とする算術演算の法則に従います。ここで、n は、整数の特定のサイズの値表現のビット数です。

出典:ドラフト N3690 §3.9.1 センテンス 4

これは、結果の符号なし整数型で表現できない結果が、結果の符号なし整数型で表現できる最大値よりも 1 大きい数値を法として減らされるため、符号なし算術演算がオーバーフローしないことを意味します。

出典: §3.9.1 のドラフト N3690 Note 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有効なプログラムでは、符号付き intxは常により小さいためx+1(符号付きオーバーフローは有効な動作とは見なされないため) 、コンパイラは生成されたコードのテストと分岐を自由にスキップできます。ただし、に置き換えるintunsigned int、コンパイラはテスト用と else 分岐用のコードを生成する必要があります。これは、符号なしの型の場合、x > x+1.

たとえば、clang はfootoのコードをコンパイルします。

foo():                                # @foo()
        push    rax
        call    do_something()
        pop     rax
        jmp     do_something()       # TAILCALL

ここでは、頌歌がdo_something2 回呼び出しているだけで ( の奇妙な処理を除いて)、実際にはrax言及されていないことがわかります。do_something_elseによってほぼ同じコードが生成されgccます。

于 2012-04-04T12:51:26.927 に答える
2

符号付きオーバーフローは、C++ では未定義の動作です。

例えば:

INT_MIN - 1

-INT_MIN

未定義の動作を呼び出す式です。

SHRT_MIN - 1および16 ビットと 32-SHRT_MINビットの環境では未定義の動作ではありません。これは、整数昇格ではオペランドが最初に昇格されるためです。16 ビットおよびの環境では、これらの式も未定義の動作です。shortintintshortint

于 2012-04-04T13:08:05.537 に答える
1

通常、はい。ただし、これは C++ であり、C++ は C++ 標準によって規制されているため、オーバーフローは未定義の動作であることを知っておく必要があります。

あなたが述べたことはおそらくほとんどのプラットフォームに当てはまりますが、決して保証されているわけではないので、それに依存しないでください.

于 2012-04-04T12:47:31.770 に答える
0

新しい値SHRT_MAXは未定義である必要はありません。

于 2012-04-04T12:47:38.960 に答える