Intをcharに切り捨てる-それは定義されていますか?
-
28-10-2019 - |
質問
unsigned char a, b;
b = something();
a = ~b;
静的アナライザは、おそらく次の理由で、最後の行で切り捨てを訴えました b
ビットが反転される前にintに昇格され、結果はint型になります。
私は昇格されたint-ifの最後のバイトにのみ興味があります b
0x55だった、私は必要です a
になります。私の質問は, cの仕様は、切り捨てがどのように起こるかについて何かを言っていますか, 、またはそれは実装定義/未定義ですか?それは保証されていますか a
常に私が期待する値が割り当てられますか、適合したプラットフォームで間違っている可能性がありますか?
もちろん、割り当てる前に結果をキャストすると静的アナライザは沈黙しますが、最初にこの警告を無視しても安全かどうかを知りたいです。
解決
切り捨ては、 C99標準
...新しいタイプが符号なしの場合、値が新しいタイプの範囲内になるまで、新しいタイプで表現できる最大値より1つ多い値を繰り返し加算または減算することにより、値が変換されます。
CHAR_BITの例== 8、sizeof(unsigned char)== 1、sizeof(int)== 4
したがって、0x55は
int
に変換され、0x00000055に変換されてから、0xFFFFFFAAに否定され、 ジェネラコディセタグプレまたは、ご想像のとおり、単純なジェネラコディセタグコードとして
他のヒント
C標準では、符号なしタイプに対してこれを指定しています。
符号なしを含む計算 オペランドがオーバーフローすることはありません。 で表すことができない結果 結果の符号なし整数型は 1である数を法として減少 その最大値よりも大きい 結果で表すことができます タイプ。
この場合、
unsigned char
が8ビットの場合、結果は256を法として減少します。つまり、b
が0x55
の場合、a
は実際に0xAA
になります。ただし、
unsigned char
が8ビットよりも広い場合(これは完全に合法です)、異なる結果が得られることに注意してください。結果として0xAA
を移植可能に取得できるようにするには、次を使用できます。 ジェネラコディセタグプレ(ビット単位であり、
unsigned char
が8ビットのプラットフォームで最適化する必要があります)。符号付きタイプを使用する場合、結果は実装によって定義されることにも注意してください。
希望どおりに動作します。値をキャストしても安全です。
この特定のコード例は安全です。しかし、~演算子の緩い使用に対して警告する理由があります。
この背後にある理由は、小さな整数変数の~は、Cの暗黙の整数プロモーションのために、より複雑な式の潜在的なバグであるということです。あなたが次のような表現を持っていたら想像してみて
a = ~b >> 4;
予想されていたようにゼロでシフトすることはありません。
静的アナライザがMISRA-Cを含めるように設定されている場合、MISRAは小さな整数型に対する操作の結果を明示的に期待される型(この場合はunsigned char)に型
Win32マシンの場合を考えてみましょう。
整数は4バイトであり、それをcharに変換すると、残りの3バイトが削除されたかのようになります。
charをcharに変換しているので、何にプロモートされているかは関係ありません。
~b will add 3 bytes at the left change 0s to 1 and then remove... It does not affect your one right byte.
同じ概念がさまざまなアーキテクチャ(16ビットまたは64ビットマシン)に適用されます
リトルエンディアンであると想定