Pertimbangkan struct berikut:
struct s {
int a, b;
};
Biasanya 1 , struct ini akan memiliki ukuran 8 dan alignment 4.
Bagaimana jika kita membuat dua struct s
objek (lebih tepatnya, kita menulis ke dalam penyimpanan yang dialokasikan dua objek tersebut), dengan objek kedua tumpang tindih yang pertama?
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);
Apakah ada sesuatu tentang program ini perilaku yang tidak terdefinisi? Jika demikian, di mana itu menjadi tidak terdefinisi? Jika bukan UB, apakah dijamin untuk selalu mencetak yang berikut ini:
o2.a=3
o2.b=4
o1.a=1
o1.b=3
Secara khusus, saya ingin tahu apa yang terjadi pada objek yang ditunjukkan oleh o1
kapan o2
, yang tumpang tindih, ditulis. Apakah masih diizinkan mengakses bagian yang belum dibuka ( o1->a
)? Apakah mengakses bagian clobbered o1->b
sama dengan mengakses o2->a
?
Bagaimana tipe efektif berlaku di sini? Aturannya cukup jelas ketika Anda berbicara tentang objek yang tidak tumpang tindih dan pointer yang menunjuk ke lokasi yang sama dengan toko terakhir, tetapi ketika Anda mulai berbicara tentang jenis bagian efektif dari objek atau objek yang tumpang tindih, itu kurang jelas.
Adakah yang akan berubah jika tulisan kedua dari jenis yang berbeda? Jika anggota mengatakan int
dan short
bukan dua int
?
Ini adalah godbolt jika Anda ingin bermain dengannya di sana.
1 Jawaban ini berlaku untuk platform di mana ini tidak terjadi juga: misalnya, beberapa mungkin memiliki ukuran 4 dan penyelarasan 2. Pada platform di mana ukuran dan penyelarasan adalah sama, pertanyaan ini tidak akan berlaku karena sejajar, objek yang tumpang tindih akan tidak mungkin, tapi saya tidak yakin apakah ada platform seperti itu.