17

f0f1を同じバイトにパックする実装の場合、以下のプログラムは定義されていますか?

struct S0 {
       unsigned f0:4;
       signed f1:4;
} l_62;

int main (void) {
       (l_62.f0 = 0) + (l_62.f1 = 0);
       return 0;
}

C99とC11の答えが違うと思う理由があれば興味があります。

C99 では、6.5:2 しか見つかりませんでした。

前のシーケンス ポイントと次のシーケンス ポイントの間で、オブジェクトに格納されている値は、式の評価によって最大 1 回変更されます。[...]

この段落が上記のプログラムにどのような影響を与えるかは、私には明確ではありません。

多数のランダム化されたテストに基づいて、ほとんどのコンパイラは、2 つの割り当てが干渉しないコードを生成するようです。

4

2 に答える 2

3

C11 は、隣接する名前付きビット フィールドを同じメモリ位置の一部と見なします。このようなビット フィールドは、アトミックに更新されることが保証されていません。つまり、1 つの更新が他の更新の前に明示的に順序付けられていない場合、動作は未定義です。3.14 memory locationthen には、いつ 2 つのフィールドが異なるメモリ位置にあると見なすことができるかについての詳細な説明もあります。したがって、それらの更新を個別に考慮することができます。

構造を変更する場合

struct S0 {
       unsigned f0:4;
       int :0;
       signed f1:4;
} l_62;

2 つのビット フィールドの間にこの奇妙な「メモリ ロケーション セパレータ」があるように、コードは正常であることが保証されます。

C99 の場合はもっと複雑なようです。メモリ位置の詳細な概念はありません。Linux カーネル メーリング リストでの最近の議論では、通常、ビット フィールドのすべてのペアに対して、それらのいずれかを更新するときに原子性が保証されるという主張がありました。その議論の出発点は、gcc が予期しない方法でビット フィールドに隣接する非ビット フィールドを汚染し、偽のクラッシュを引き起こしたケースでした。

于 2012-02-05T20:43:45.310 に答える
0

ここでの割り当ては、構造体メンバーです。それらがたまたま同じストレージを共有しているという事実は、ロジックに影響を与えないはずです。実際、あなたは実際に同じものに割り当てをしていません。

もちろん、私は言語弁護士ではありません。

于 2012-02-05T20:03:55.033 に答える