web-dev-qa-db-ja.com

負のintがunsigned intよりも大きいのはなぜですか?

int main(void) 
{ 
     unsigned int y = 10; 
     int x = – 4; 
     if (x > y) 
        Printf("x is greater");
     else 
        Printf("y is greater"); 
     getch(); 
     return (0); 
} 

Output: x is greater

符号なしなので、出力はyの方が大きいと思いました。これの背後にある理由は何ですか?

42
Slashr

int値がunsigned intにプロモートされるためです。特に、32ビットマシンでは0xFFFFFFFCであり、unsigned int4294967292であり、10よりかなり大きい

C99 6.3.1.1-p2

Intが元の型のすべての値を表すことができる場合(ビットフィールドの幅によって制限される)、値はintに変換されます。それ以外の場合は、nsigned intに変換されます。これらは整数プロモーションと呼ばれます。他のすべてのタイプは、整数の昇格によって変更されません。

変換を実行するには:

C99 6.3.1.3-p2

それ以外の場合、新しいタイプが符号なしの場合、値が新しいタイプの範囲内になるまで、新しいタイプで表すことができる最大値よりも1だけ多く加算または減算することによって値が変換されます。

これは基本的に「UINT_MAX + 1を追加する」という意味です(とにかく読んでいます)。

プロモーションがunsigned int側で行われた理由について。優先順位:

C99 6.3.1.8-p1

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

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

これは、intunsigned charが期待どおりに機能することを示しています。

テスト

int main()
{
    int x = -4;
    unsigned int y = 10;
    unsigned char z = 10;

    if (x > y)
        printf("x>y\n");
    else
        printf("x<y\n");

    if (x > z)
        printf("x>z\n");
    else
        printf("x<z\n");
    return 0;
}

出力

x>y
x<z

それをよく見てください。

45
WhozCraig

符号付き値と符号なし値の比較は、「符号なしスペース」で行われます。つまり、符号付きの値は、UINT_MAX + 1を追加することで符号なしに変換されます。負の値に2の補数を使用する実装では、内部で値を特別に処理する必要はありません。

この例では、-40x100000000-4 = 0xFFFFFFFCに変換されます。これは明らかに> 10です。

11
glglgl

Cで2つの値を比較する場合、両方とも同じタイプである必要があります。この場合(intおよびunsigned int)、最初にint値がunsigned intに変換されます。

次に、Cの符号なし整数演算は、その型の最大値+ 1を法として実行されます(つまり、「ループ」するため、UINT_MAX + 10になり、その逆も同様です)。したがって、負の値を符号なしに変換すると、非常に大きな数になります。

規格の関連セクションには次のように書かれています。

6.3.1.3符号付きおよび符号なし整数

2
それ以外の場合、新しいタイプが符号なしの場合、値が新しいタイプの範囲内になるまで、新しいタイプで表現できる最大値より1つ多い値を繰り返し加算または減算することにより、値が変換されます。

4
melpomene

intunsigned intを比較すると、intunsigned intに変換されます。 intからunsigned intへの変換は、UINT_MAX+1を追加することによって行われます(intは負であることに注意してください)。だから実際にあなたは比較しています:

if (-3 + UINT_MAX > 10)  //Since -4 is converted to UINT_MAX+1-4

それは本当です。

4
Maroun

Int値の最初のビットは、それが正か負かを定義するために使用されます。 (1 =負、0正)比較の前に、両方の変数がunsigned intにキャストされ、最初のビットの1が数値の一部として解釈されます。

このコードは正常に機能するはずです:

int main(void) 

 { 

    unsigned int y = 10; 
    int x = – 4; 
    if (x > (int) y) 
    Printf("x is greater");
    else 
    Printf ("y is greater"); 
    getch ( ); 
    return (0); 

 } 
1
Jeremie