4

C++ プログラムの次の部分を考えてみましょう。コンソールに表示される値はコメントとして提供されます。

{ // case 1
unsigned int x = 10; 
unsigned int y = 20; 
std::cout << "u/u x - y: " << x-y << std::endl; // 4294967286
}   

{ // case 2
int x = 10; 
int y = 20; 
std::cout << "s/s x - y: " << x-y << std::endl; // -10
}   

{ // case 3
unsigned int x = 10; 
int y = 20; 
std::cout << "u/s x - y: " << x-y << std::endl; // 4294967286
}   

{ // case 4
int x = 10; 
unsigned int y = 20; 
std::cout << "s/u x - y: " << x-y << std::endl; // 4294967286
}

C++ (gcc 4.7.2 で試行) が式から型 (より具体的には、その符号) を定義する方法を理解しようとしています。ケース 1、3、および 4 の場合、通常の算術変換では、両方の値を unsigned int に昇格する必要があります。

 10 = b00000000000000000000000000001010
 20 = b00000000000000000000000000010100

次に、2 の補数をとって -20 を取得し、それを加算します。

 10 = b00000000000000000000000000001010
-20 = b11111111111111111111111111101100
      b11111111111111111111111111110110

これを符号なし整数として解釈すると、4294967286 になります。

明らかに、ケース 2 でも同じ計算/結果が得られます。ただし、通常の算術変換では、両方のオペランドが符号付き int として解釈される必要があり、結果も符号付き整数として解釈されるようです。

このことから、オペランドが通常の算術変換の後に署名されている場合、結果は署名されていると推測しています。それ以外の場合、結果は符号なしです。

だから、私の質問は次のとおりです。

  1. 私の推理は正しいですか?
  2. 標準はこれをどこで定義していますか? CまたはC++標準でこれへの参照を見つけることができません。
  3. 他の操作はどうですか?+、などは同じように機能すると思い*ますが、シフトと論理演算はどうですか?

編集:これは(符号付き+符号なし)のC++ 11タイプに関連しているようです? 、しかし、私の質問の重要な部分は、そこで受け入れられた答えから欠落しているようです.通常の算術変換の後、式の結果は常に両方のオペランドの型になりますか?

4

2 に答える 2

7

変換は、整数変換ランクの原則に従います。簡単に言えば、整数オペランドは次のように処理されます。

最初に、より小さい各オペランドは(元の型のすべての値が適合する場合) にint変換され、適合しない場合は に変換されます。intunsigned int

その後、(場合によっては変換された) オペランドの型が次の場合:

  • まったく同じで、変換は行われません。

  • 同じサイズの場合、符号なしが優先されます。

  • 異なるサイズで、小さいものは大きいものに変換されます。大きい方が符号なしの場合、小さい方も符号なしに変換されます。

この変換により、オペランドが同じ型に変換されます。これは、結果の型でもあります。

[expr]§9C++11 標準でカバーされています。[conv]や とも密接に関係してい[conv.rank]ます。これが正確に適用されるオペレーターについては、 のサブチャプターの個々のオペレーターの説明で説明されてい[expr]ます。

于 2013-03-27T15:07:42.370 に答える
2

OK、それは簡単です、私は標準を読み違えただけです... C++ 11、§5 [expr] p9から:

算術型または列挙型のオペランドを想定する多くの二項演算子は、同様の方法で変換を行い、結果の型を生成します。目的は、結果の型でもある共通の型を生成することです。このパターンは、通常の算術変換と呼ばれます...

于 2013-03-27T15:07:12.807 に答える