ビットフィールドにアクセスするたびにCコンパイラがモジュロ2^nを実行することを信頼できますか?または、以下のようなコードがオーバーフローを出力しないコンパイラ/最適化はありますか?
struct {
uint8_t foo:2;
} G;
G.foo = 3;
G.foo++;
if(G.foo == 0) {
printf("Overflow\n");
}
よろしくお願いします、フロリアン
ビットフィールドにアクセスするたびにCコンパイラがモジュロ2^nを実行することを信頼できますか?または、以下のようなコードがオーバーフローを出力しないコンパイラ/最適化はありますか?
struct {
uint8_t foo:2;
} G;
G.foo = 3;
G.foo++;
if(G.foo == 0) {
printf("Overflow\n");
}
よろしくお願いします、フロリアン
はい、ビットフィールドが符号なし型で宣言されている限り、Cコンパイラがここで正しいことを実行することを信頼できますuint8_t
。C99標準§6.2.6.1/3から:
unsignedビットフィールドおよびunsignedchar型のオブジェクトに格納されている値は、純粋なバイナリ表記を使用して表す必要があります。40)
§6.7.2.1/9から:
ビットフィールドは、指定されたビット数で構成される符号付きまたは符号なし整数型として解釈されます。104)値0または1がタイプの非ゼロ幅のビットフィールドに格納されている
_Bool
場合、ビットフィールドの値は格納されている値と等しくなります。
そして§6.2.5/9(強調鉱山)から:
符号付き整数型の非負値の範囲は、対応する符号なし整数型のサブ範囲であり、各型での同じ値の表現は同じです。31) 結果の符号なし整数型で表現できない結果は、結果の型で表現できる最大値より1大きい数を法として減少するため、符号なしオペランドを含む計算はオーバーフローすることはありません。
そうです、標準に準拠しているコンパイラはG.foo
、他の望ましくない副作用なしに0までオーバーフローすることを確信できます。
いいえ。コンパイラはフィールドに 2 ビットを割り当て、3 をインクリメントすると 100b になり、2 ビットに配置すると 0 になります。
簡単な答え: はい、モジュロ 2^n が発生することを信頼できます。
あなたのプログラムで
G.foo++;
は、実際には と同等G.foo = (unsigned int)G.foo + 1
です。
unsigned int 演算では、常に 2^(ビット単位の unsigned int のサイズ) の結果が生成されます。次に、最小の重みの 2 ビットが に格納されG.foo
、ゼロが生成されます。