12

重複の可能性:
二項演算子の両側の符号が異なる場合、プロモーションルールはどのように機能しますか?

整数拡張とC++でのオーバーフローに頭を悩ませようとしています。私はいくつかの点で少し混乱しています:

a)次のコードセグメントがある場合:

int i = -15; 
unsigned j = 10; 
std::cout << i + j;

-5 % UINT_MAXます。これは、式i + jが自動的に符号なしにプロモートされるためですか?私は標準(4.13)を読み込もうとしていました:

— The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type.

これを間違って読んでいるかどうかはわかりませんが、それが本当なら、なぜi + j署名されていないのですか?

b)前のセグメントに追加すると、次のようになります。

int k = j + i;

それはに評価されてい-5ます。式j + iを最初に評価4294967291して、システムに与え、それをjに設定するべきではありませんか?それは範囲外であるはずです、それでこの振る舞いは未定義ですか?なぜ私が得るのかわかりません-5

c)を使用してa)からセグメントを少し変更すると、次のようになりshortます。

short i = -15;
unsigned short j = 10;
std::cout << i + j;

これを実行すると、a)と同じ結果が得られると思いましたが、-5 % USHRT_MAX。ただし、これを実行すると、が得られ-5ます。short使用すると、とは異なる値が得られるのはなぜintですか?

d)符号付き積分のオーバーフロー動作は未定義であることを常に学びました。例:int r = ++INT_MAX未定義になります。

ただし、符号なしオーバーフローが発生した場合は、数量が定義されます。例:unsigned a = ++UINT_MAX、の場合、aは。になります0。あれは正しいですか?

しかし、規格はそれについて何も述べていないようでした。本当?もしそうなら、それはなぜですか?

4

1 に答える 1

4

a)§5/ 9から:

算術型または列挙型のオペランドを期待する多くの二項演算子は、同様の方法で変換を引き起こし、結果型を生成します。目的は、結果のタイプでもある共通のタイプを生成することです。このパターンは通常の算術変換と呼ばれ、次のように定義されます。

  • いずれかのオペランドがタイプのlong double場合、もう一方はに変換されlong doubleます。
  • それ以外の場合、一方のオペランドがdouble、の場合、もう一方はに変換されdoubleます。
  • それ以外の場合、一方のオペランドがfloat、の場合、もう一方はに変換されfloatます。
  • それ以外の場合、積分昇格(4.5)は両方のオペランドで実行されます。
  • 次に、どちらかのオペランドがunsigned longもう一方のオペランドである場合は、に変換されunsigned longます。
  • それ以外の場合、一方のオペランドがalong intで、もう一方のオペランドがaであるunsigned int場合、aがalong intのすべての値を表すことができる場合unsigned int、は;unsigned intに変換されます。long intそれ以外の場合は、両方のオペランドがに変換されunsigned long intます。
  • それ以外の場合、一方のオペランドがlong、の場合、もう一方はに変換されlongます。
  • それ以外の場合、一方のオペランドがunsigned、の場合、もう一方はに変換されunsignedます。

[注:それ以外の場合、残りの唯一のケースは、両方のオペランドがint]であるということです。

したがって、はにj昇格され、符号なし整数演算を使用して加算が実行されます。unsignediunsigned

b)これはUBです。加算の結果はunsigned int((a)のように)であるためint、割り当てでオーバーフローします。

c)§4.5/ 1から:

タイプ、、、、の右辺値char、またはsigned charソースタイプのすべての値を表すことができる場合は、タイプの右辺値に変換できます。それ以外の場合は、ソース右辺値をタイプの右辺値に変換できます。unsigned charshort intunsigned short intintintunsigned int

したがって、4バイトは2バイトまたはintの任意の値を表すことができるため、両方が(§5.9の統合プロモーションルールに従って)にプロモートされ、sとして追加されます。shortunsigned shortintint

d)§3.9.1/ 4から:

宣言された符号なし整数は、 2 nunsignedを法とする算術の法則に従うものとします。ここで、nは、その特定のサイズの整数の値表現のビット数です。

したがって、UINT_MAX+1は合法(UBではない)であり、0に等しくなります。

于 2012-10-15T05:21:17.180 に答える