Ini bukan perilaku yang tidak terdefinisi , terlepas dari apa yang dikatakan seseorang, resmi atau tidak , karena itu ditentukan oleh standar. p->s
, kecuali jika digunakan sebagai nilai l, mengevaluasi ke penunjuk yang identik dengan (char *)p + offsetof(struct T, s)
. Secara khusus, ini adalah char
penunjuk yang valid di dalam objek malloc'd, dan ada 100 (atau lebih, tergantung pada pertimbangan penyelarasan) alamat berturut-turut segera mengikutinya yang juga valid sebagai char
objek di dalam objek yang dialokasikan. Fakta bahwa pointer diturunkan dengan menggunakan ->
bukannya secara eksplisit menambahkan offset ke pointer yang dikembalikan oleh malloc
, cast to char *
, tidak relevan.
Secara teknis, p->s[0]
adalah elemen tunggal dari char
array di dalam struct, beberapa elemen berikutnya (misalnya p->s[1]
melalui p->s[3]
) kemungkinan besar padding byte di dalam struct, yang dapat rusak jika Anda melakukan penugasan ke struct secara keseluruhan tetapi tidak jika Anda hanya mengakses individu anggota, dan elemen lainnya adalah ruang tambahan dalam objek yang dialokasikan yang dapat Anda gunakan secara bebas sesuka Anda, selama Anda mematuhi persyaratan penyelarasan (dan char
tidak memiliki persyaratan penyelarasan).
Jika Anda khawatir bahwa kemungkinan tumpang tindih dengan byte padding di struct mungkin entah bagaimana memanggil setan hidung, Anda dapat menghindari ini dengan mengganti 1
in [1]
dengan nilai yang memastikan bahwa tidak ada padding di akhir struct. Cara sederhana namun boros untuk melakukan ini adalah dengan membuat struct dengan anggota yang identik kecuali tidak ada larik di akhir, dan digunakan s[sizeof struct that_other_struct];
untuk larik. Kemudian, p->s[i]
secara jelas didefinisikan sebagai elemen dari array di struct untuk i<sizeof struct that_other_struct
dan sebagai objek char di alamat setelah akhir dari struct untuk i>=sizeof struct that_other_struct
.
Sunting: Sebenarnya, dalam trik di atas untuk mendapatkan ukuran yang tepat, Anda mungkin juga perlu meletakkan gabungan yang berisi setiap tipe sederhana sebelum larik, untuk memastikan bahwa larik itu sendiri dimulai dengan perataan maksimal daripada di tengah padding elemen lain . Sekali lagi, saya tidak percaya semua ini perlu, tapi saya menawarkannya untuk pengacara bahasa paling paranoid di luar sana.
Sunting 2: Tumpang tindih dengan padding byte jelas bukan masalah, karena bagian lain dari standar. C mensyaratkan bahwa jika dua struct setuju dalam urutan awal elemen mereka, elemen awal yang sama dapat diakses melalui penunjuk ke salah satu tipe. Akibatnya, jika sebuah struct identik dengan struct T
tetapi dengan larik akhir yang lebih besar dideklarasikan, elemen s[0]
tersebut harus bertepatan dengan elemen s[0]
di struct T
, dan keberadaan elemen tambahan ini tidak dapat mempengaruhi atau dipengaruhi dengan mengakses elemen umum dari struct yang lebih besar. menggunakan penunjuk ke struct T
.