コンパイラが符号付き/符号なしの不一致を検出した場合、どのようなアクションを実行しますか?署名された番号は署名されていない番号にキャストされますか、またはその逆ですか?なぜ?
3 に答える
オペランドが整数で符号なしの値がある場合、符号なしへの変換が行われます。例えば:
-1 > (unsigned int)1 // as -1 will be converted to 2^nbits-1
int->unsigned int への変換: n>=0 -> n; n<0 -> n (mod 2^nbits)、たとえば -1 は 2^nbits-1 になります
変換 unsigned int->int は: n <= INT_MAX -> n; n > INT_MAX -> 実装定義
宛先の型が符号なしの場合、結果の値は、ソースの整数と一致する最小の符号なし整数になります (モジュロ 2^n で、n は符号なしの型を表すために使用されるビット数です)。
宛先の型が符号付きの場合、値が宛先の型 (およびビット フィールド幅) で表現できる場合、値は変更されません。それ以外の場合、値は実装定義です。
C++ が、C が符号付き/符号なしの変換を処理する方法から逸脱しているとは思わない:
unsigned
オペランドが含まれる場合、変換規則はより複雑になります。問題は、さまざまな整数型のサイズに依存するため、符号付き値と符号なし値の比較がマシンに依存することです。(K&R)
考慮すべき重要な要素の 1 つは、型の 1 つがlong
整数であるかどうかです。これは、整数の昇格に影響するためです。たとえば、long int
が と比較され、unsigned int
がlong int
のすべての値を表すことができるunsigned int
場合、unsigned int
は に変換されますlong int
。(それ以外の場合は、両方とも単に に変換されますunsigned long int
。)
ただし、ほとんどの場合、不一致が見つかった場合、コンパイラは符号付き整数を符号なし整数に変換する必要があります。
コンパイラ固有の可能性があります。「Cコンパイラの符号付き/符号なしの不一致の警告を無効にする必要がありますか?」という質問を見ると、「litb」の場合、変数signed-varが符号なしの値に「プロモート」されていることがわかります。
いずれの場合も、1つの変数が特定の値に達すると(つまり、最上位ビットが設定されると)、コンパイラがこの状況を処理する「正しい」方法はありません。したがって、そのような警告がある場合は、必ずそれを取り除いてください;)