16

暗黙的な変換に関して、符号なしの型オペランドと符号付きの型オペランドがあり、符号なしのオペランドの型が符号付きのオペランドの型と同じ(または大きい)場合、符号付きのオペランドが変換されることを理解しています無署名に。

そう:

unsigned int u = 10;  
signed int s = -8;

std::cout << s + u << std::endl;

//prints 2 because it will convert `s` to `unsigned int`, now `s` has the value
//4294967288, then it will add `u` to it, which is an out-of-range value, so,
//in my machine, `4294967298 % 4294967296 = 2`

私が理解していないこと - 符号付きオペランドが符号なしオペランドよりも大きな型を持っている場合、私はそれを読みました:

  • 符号なし型のすべての値がより大きな型に収まる場合、符号なしオペランドは符号付き型に変換されます

  • 符号なし型の値がより大きな型に収まらない場合、符号付きオペランドは符号なし型に変換されます

したがって、次のコードで:

signed long long s = -8;
unsigned int u = 10;
std::cout << s + u << std::endl;

uint 値は signed long long に収まるため、signed long long に変換されますか??

その場合、小さい型の値が大きい型の値に収まらないのはどのシナリオですか?

4

3 に答える 3

26

標準からの関連する引用:

5 式 [expr]

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

[等号の種類または等号の種類に関する 2 節を省略]

— それ以外の場合、符号なし整数型を持つオペランドのランクが他のオペランドの型のランク以上である場合、符号付き整数型を持つオペランドは、符号なし整数型を持つオペランドの型に変換されます。

— それ以外の場合、符号付き整数型のオペランドの型が符号なし整数型のオペランドの型のすべての値を表すことができる場合、符号なし整数型のオペランドは符号付き整数型のオペランドの型に変換されます。

— それ以外の場合、両方のオペランドは、符号付き整数型のオペランドの型に対応する符号なし整数型に変換されます。

システム上のsizeof(int) < sizeof(long) == sizeof(long long)上記の 3 つの節のそれぞれについて、次の 3 つの事例を考えてみましょう(他の事例に容易に適応可能) 。

#include <iostream>

signed int s1 = -4;
unsigned int u1 = 2;

signed long int s2 = -4;
unsigned int u2 = 2;

signed long long int s3 = -4;
unsigned long int u3 = 2;

int main()
{
    std::cout << (s1 + u1) << "\n"; // 4294967294
    std::cout << (s2 + u2) << "\n"; // -2 
    std::cout << (s3 + u3) << "\n"; // 18446744073709551614  
}

出力付きのライブ例

第 1 節: 等しいランクの型なので、signed intオペランドは に変換されunsigned intます。これには、(2 の補数を使用して) 値を出力する値変換が伴います。

2 番目の句: 符号付き型はランクが高く、(このプラットフォームでは!) 符号なし型のすべての値を表すことができるため、符号なしオペランドは符号付き型に変換され、-2 を取得します。

3 番目の節: 符号付き型は再びランクが高くなりますが、(このプラットフォームでは!) 符号なし型のすべての値を表すことはできないため、両方のオペランドが に変換され、符号付きunsigned long longオペランドの値変換の後、出力された値が得られます。

符号なしオペランドが十分に大きい場合 (たとえば、これらの例では 6)、符号なし整数のオーバーフローにより、最終結果は 3 つの例すべてで 2 になることに注意してください。

(追加) これらの型を比較す​​ると、さらに予想外の結果が得られることに注意してください。上記の例 1 を<次のように考えてみましょう。

#include <iostream>

signed int s1 = -4;
unsigned int u1 = 2;
int main()
{
    std::cout << (s1 < u1 ? "s1 < u1" : "s1 !< u1") << "\n";  // "s1 !< u1"
    std::cout << (-4 < 2u ? "-4 < 2u" : "-4 !< 2u") << "\n";  // "-4 !< 2u"
}

2uはサフィックスunsignedによって明示的に作成されるため、同じ規則が適用されます。そして、結果はおそらく、C++ での記述時に-4 < 2uを比較したときに期待するものではありません...-4 < 2u

于 2013-07-24T11:56:49.697 に答える
2

signed intには収まりませんunsigned long long。したがって、次の変換が行われます: signed int-> unsigned long long.

于 2013-07-24T11:44:05.383 に答える