54

このコード スニペットを参照してください

int main()
{ 
 unsigned int a = 1000;
 int b = -1;
 if (a>b) printf("A is BIG! %d\n", a-b);
 else printf("a is SMALL! %d\n", a-b); 
 return 0;
}   

これにより、出力が得られます: a is SMALL: 1001

ここで何が起こっているのかわかりません。ここで > 演算子はどのように機能しますか? 「a」が「b」よりも小さいのはなぜですか? 実際に小さい場合、差として正の数 (1001) が得られるのはなぜですか?

4

7 に答える 7

63

異なる整数型間の二項演算は、いわゆる通常の算術変換によって定義された「共通」型内で実行されます(言語仕様 6.3.1.8 を参照)。あなたの場合、「一般的な」タイプはunsigned int. これは、intオペランド (your b) が比較の前に変換されることunsigned int、および減算を実行する目的で変換されることを意味します。

-1が結果に変換されるときはunsigned int、可能な最大unsigned int値です ( と同じUINT_MAX)。言うまでもなく、それはあなたの符号なしの値より1000も大きくなるでしょう。コード内のは分岐に解決されるはずです。これは、実験で観察したものです。a > ba(unsigned) bifelse

減算にも同じ変換規則が適用されます。Youra-bは実際には と解釈されa - (unsigned) b、結果の型はunsigned intです。このような値は、符号付きの値でのみ機能する%dため、書式指定子を使用して出力することはできません。で出力しようとすると、未定義の動作が発生するため、表示される値は (実際には論理的な決定論的説明がありますが)、C 言語の観点からはまったく意味がありません。%d%d

編集:実際には、未定義の動作部分について間違っている可能性があります。C 言語仕様によると、対応する符号付きおよび符号なし整数型の範囲の共通部分は、同一の表現を持つものとします (脚注 31 によると、「関数への引数としての互換性」を意味します)。したがって、式の結果は上記のようにa - b符号なしであり、何かが欠けていない限り、この特定の符号なし値を指定子とともに出力することは合法です。での印刷は未定義ですが、問題ありません。1001%dint(unsigned) INT_MAX + 1%d1001u

于 2010-01-18T09:37:48.047 に答える
15

intが 32 ビットの典型的な実装では、-1 に変換するunsigned intと 4,294,967,295 になり、実際には 1000 以上になります。

unsigned世界で引き算を扱っても、1000 - (4,294,967,295) = -4,294,966,295 = 1,001それはあなたが得るものです。

と比較するとgccが警告を出すのはそのためです。(警告が表示されない場合は、フラグを渡します。)unsignedsigned-Wsign-compare

于 2010-01-18T09:25:10.433 に答える
1
 #include<stdio.h>
 int main()
 {
   int a = 1000;
   signed int b = -1, c = -2;
   printf("%d",(unsigned int)b);
   printf("%d\n",(unsigned int)c);
   printf("%d\n",(unsigned int)a);

   if(1000>-1){
      printf("\ntrue");
   }
   else 
     printf("\nfalse");
     return 0;
 }

このためには、演算子の優先順位を理解する必要があります

  1. 関係演算子は左から右に機能します...だから、それが来るとき

    もし(1000>-1)

次に、最初に -1 を符号なし整数に変更します。これは、デフォルトで int が符号なし数値として扱われ、範囲が符号なし数値より大きいためです。

-1 は符号なしの数値に変化し、非常に大きな数値に変化します

于 2018-09-12T12:30:55.537 に答える
0

ハードウェアは、符号付きと符号付き、および符号なしと符号なしを比較するように設計されています。

算術結果が必要な場合は、最初に符号なしの値をより大きな符号付きの型に変換します。それ以外の場合、コンパイラは、比較が実際には符号なしの値の間であると想定します。

そして、-1は1111..1111として表されるので、非常に大量です...最大...符号なしとして解釈された場合。

于 2012-04-20T05:26:17.807 に答える
0

符号なしの比較、つまり 1000 を 2^32 - 1 と比較しています。

printf の %d のため、出力は署名されています。

注意: 符号付きオペランドと符号なしオペランドを混在させたときの動作は、コンパイラ固有のものです。それらを避けて、疑わしい場合はキャストするのが最善だと思います。

于 2010-01-18T09:23:19.513 に答える
0

比較する簡単な方法を見つけてください。unsigned 宣言を取り除くことができない場合 ([NSArray count] など) に役立つ可能性があります。「unsigned int」を「int」に強制するだけです。

間違っている場合は修正してください。

if (((int)a)>b) {
    ....
}
于 2012-04-02T13:07:29.547 に答える