次の構造体について考えてみましょう。
struct s {
int a, b;
};
典型的には1、この構造体は、サイズ8と位置合わせ4を有するであろう。
2つのstruct s
オブジェクトを作成し(より正確には、2つのオブジェクトを割り当てられたストレージに書き込みます)、2番目のオブジェクトが最初のオブジェクトと重なる場合はどうなりますか?
char *storage = malloc(3 * sizeof(struct s));
struct s *o1 = (struct s *)storage; // offset 0
struct s *o2 = (struct s *)(storage + alignof(struct s)); // offset 4
// now, o2 points half way into o1
*o1 = (struct s){1, 2};
*o2 = (struct s){3, 4};
printf("o2.a=%d\n", o2->a);
printf("o2.b=%d\n", o2->b);
printf("o1.a=%d\n", o1->a);
printf("o1.b=%d\n", o1->b);
このプログラムについて未定義の動作はありますか?もしそうなら、それはどこで未定義になりますか?UBでない場合、常に以下を出力することが保証されていますか?
o2.a=3
o2.b=4
o1.a=1
o1.b=3
特に、それがオーバーラップしているが書き込まれたo1
ときo2
にポイントされたオブジェクトがどうなるか知りたい。取り除かれていない部分(o1->a
)へのアクセスは引き続き許可されますか?破壊された部分へのアクセスは、アクセスo1->b
と同じo2->a
ですか?
ここで効果的なタイプはどのように適用されますか?オーバーラップしていないオブジェクトと、最後のストアと同じ場所を指すポインターについて話しているときは、ルールは十分に明確ですが、オブジェクトの部分の有効なタイプまたはオーバーラップしているオブジェクトについて話し始めると、それほど明確ではありません。
2回目の書き込みが別のタイプの場合、何か変更はありますか?メンバーが言ったint
としたら、short
2 int
つではなく?
ここでプレイしたい場合は、ここにゴッドボルトがあります。
1この回答は、これが当てはまらないプラットフォームにも当てはまります。たとえば、サイズ4と配置2があるプラットフォームもあります。サイズと配置が同じであるプラットフォームでは、配置されたオブジェクトが重なるため、この質問は当てはまりません。不可能ではありますが、そのようなプラットフォームがあるかどうかはわかりません。