異なるコンパイラでのC ++とCの間の符号なしビットフィールド整数式の一貫性のない切り捨て
編集2: 以前にC ++ソースファイルに存在していた関数がそのままCファイルに移動され、誤った結果が返され始めたときに、奇妙なテストエラーをデバッグしていました。以下のMVEにより、GCCでの問題を再現できます。しかし、気まぐれでClangを使用して(そして後でVSを使用して)例をコンパイルすると、異なる結果が得られました!これをコンパイラの1つのバグとして扱うのか、CまたはC ++標準で許可されている未定義の結果の明示として扱うのか、私にはわかりません。奇妙なことに、どのコンパイラーも式に関する警告を出しませんでした。 犯人はこの表現です: ctl.b.p52 << 12; ここでp52は、と入力されuint64_tます。組合の一部でもありcontrol_tます(下記参照)。結果は64ビットに収まるため、シフト操作はデータを失わない。ただし、Cコンパイラを使用している場合、GCCは結果を52ビットに切り捨てることを決定します。C ++コンパイラでは、結果の64ビットがすべて保持されます。 これを説明するために、以下のサンプルプログラムは、同一の本体を持つ2つの関数をコンパイルし、それらの結果を比較します。c_behavior()Cソースファイルとcpp_behavior()C ++ファイルに配置されmain()、比較を行います。 サンプルコードを含むリポジトリ:https : //github.com/grigory-rechistov/c-cpp-bitfields ヘッダーcommon.hは、64ビット幅のビットフィールドと整数の和集合を定義し、2つの関数を宣言します。 #ifndef COMMON_H #define COMMON_H #include <stdint.h> typedef union control { uint64_t q; struct { uint64_t a: 1; uint64_t b: 1; uint64_t c: 1; uint64_t d: 1; uint64_t e: 1; uint64_t f: 1; uint64_t g: …