5
unsigned char a, b;
b = something();
a = ~b;

静的アナライザーは、おそらくbビットが反転される前にintにプロモートされ、結果がint型になるため、最後の行の切り捨てについて不平を言いました。

プロモートされたintの最後のバイトにのみ関心があります。0x55の場合bは、0xAAである必要aがあります。私の質問は、C仕様は切り捨てがどのように発生するかについて何かを述べているのか、それとも実装が定義されている/定義されていないのかということです。私が期待する値が常に割り当てられることが保証されていaますか、それとも適合プラットフォームでうまくいかない可能性がありますか?

もちろん、割り当てる前に結果をキャストすると静的アナライザーが無音になりますが、そもそもこの警告を無視しても安全かどうかを知りたいと思います。

4

5 に答える 5

10

C標準では、符号なしタイプに対してこれを指定しています。

結果の符号なし整数型で表現できない結果は、結果の型で表現できる最大値より1大きい数を法として減少するため、符号なしオペランドを含む計算はオーバーフローすることはありません。

この場合、あなたunsigned charが8ビットの場合、結果は256を法として減少することを意味します。つまり、bだった場合0x55a実際には。になり0xAAます。

ただし、unsigned charが8ビットより広い場合(これは完全に合法です)、異なる結果が得られることに注意してください。結果として移植可能に取得0xAAできるようにするには、次を使用できます。

a = ~b & 0xff;

unsigned char(ビット単位であり、が8ビットのプラットフォームで最適化する必要があります)。

符号付き型を使用する場合、結果は実装定義であることに注意してください。

于 2011-05-04T10:30:58.393 に答える
6

切り捨ては、 C99標準の6.3.1.3/2で説明されているように行われます。

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


CHAR_BITの例==8、sizeof(unsigned char)== 1、sizeof(int)== 4

したがって、0x55はint0x00000055に変換され、次に0xFFFFFFAAに否定され、

      0xFFFFFFAA
    + 0x00000100 / * UCHAR_MAX + 1 * /
    ------------
      0xFFFFFEAA

    ...何度も何度も繰り返す..。

      0x000000AA

0xAAまたは、あなたが期待するように、明白に

于 2011-05-04T10:41:05.487 に答える
1

希望どおりに動作します。値をキャストしても安全です。

于 2011-05-04T10:23:40.967 に答える
0

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ビットマシン)に適用されます

リトルエンディアンであると仮定する

于 2011-05-04T10:27:54.650 に答える
0

この特定のコード例は安全です。ただし、〜演算子の緩い使用に対して警告する理由があります。

この背後にある理由は、Cの暗黙の整数昇格のために、小さい整数変数の〜がより複雑な式の潜在的なバグであるためです。次のような式がある場合を想像してみてください。

a = ~b >> 4;

予想されたように、ゼロにシフトすることはありません。

静的アナライザーにMISRA-Cが含まれるように設定されている場合、たとえば、MISRAは小さな整数型に対する操作の結果を、期待される型(この場合はunsigned char)に明示的に型キャストするように強制するため、〜演算子ごとにこの警告が表示されます。 。

于 2011-05-04T11:06:33.493 に答える