Array berurutan
Saya ingin tahu tentang kalimat dalam standar C18:
Dua pointer dibandingkan jika dan hanya jika keduanya adalah pointer nol, keduanya merupakan pointer ke objek yang sama (termasuk pointer ke objek dan subobject pada awalnya) atau fungsi, keduanya merupakan pointer ke salah satu elemen terakhir dari array yang sama objek, atau satu adalah penunjuk ke satu melewati akhir dari satu objek larik dan yang lainnya adalah penunjuk ke awal dari objek larik yang berbeda yang kebetulan langsung mengikuti objek larik pertama di ruang alamat. § 6.5.9 6
Mengapa objek yang mengikuti larik harus selalu berupa larik lain? Tidak bisa hanya menjadi objek dengan tipe yang sama dengan tipe dasar array (seperti yang intsegera mengikuti int[])?
Tidak heran saya sudah mencoba kode ini:
#include <stdio.h>
struct test { int arr[10]; int i; };
int main() {
struct test t;
int *p, *q;
p = t.arr + 10;
q = &t.i;
if (p == q)
printf("Equal pointers.");
return 0;
}
Dan itu menghasilkan petunjuk yang sama. Apakah perilaku ini tidak dijamin sama sekali, hanya kebetulan yang ditentukan implementasi?
Jawaban
OP: Mengapa objek yang mengikuti array harus selalu berupa array lain?
Itu tidak. "... awal dari larik yang berbeda ..." adalah penyederhanaan. Spesifikasi selanjutnya adalah:
Untuk keperluan operator ini, penunjuk ke objek yang bukan elemen dari larik berperilaku sama seperti penunjuk ke elemen pertama dari larik yang panjangnya satu dengan tipe objek sebagai jenis elemennya. C17dr § 6.5.9 7
OP: Tidak bisa hanya menjadi objek yang tipenya sama dengan tipe dasar array (seperti
intsegera mengikutiint[])?
Iya.
Pertama, menentukan larik di sini tidak mengecualikan / melarang satu objek. Satu objek dalam memori tidak dapat dibedakan dari larik berukuran 1.
( Sunting : Baca jawaban ini untuk kutipan dari standar yang secara eksplisit menyatakan ini ketika mengacu pada petunjuk)
Kedua, standar juga mencoba untuk mengklarifikasi pernyataan yang telah Anda kutip, dengan catatan kaki berikut menunjukkan skenario di mana aturan tersebut berlaku:
Dua objek dapat bersebelahan dalam memori karena mereka adalah elemen yang berdekatan dari larik yang lebih besar atau anggota struktur yang berdekatan tanpa padding di antara mereka, atau karena implementasi memilih untuk menempatkannya, meskipun mereka tidak terkait.
Menyatukan semuanya, apa yang coba dikatakan standar di sini adalah bahwa secara umum, dua petunjuk ke objek yang berbeda tidak boleh dibandingkan dengan yang sama. Namun, karena legal untuk menunjuk satu di luar objek array di memori, jika ada objek (array) yang berbeda di lokasi itu, masih legal untuk pointer seperti itu membandingkan sama dengan pointer ke objek yang berdekatan. Sekarang, mungkin ada atau mungkin tidak ada objek yang valid di lokasi ini, karena pilihan penyelarasan dan padding, tetapi jika ada, dapat diterima untuk membandingkan pointer ini sama.
Dalam contoh Anda, jika saya mengubah array menjadi char, pointer mungkin akan membandingkan tidak sama karena kompilator akan memilih untuk menyelaraskan int ke 4 byte (pada sebagian besar platform 32 atau 64-bit), dengan demikian memperkenalkan padding. Perilaku ini masih legal menurut standar.
#include <stdio.h>
struct test { char arr[10]; int i; };
int main() {
struct test t;
int *p, *q;
p = (int*)(t.arr + 10);
q = &t.i;
if(p == q)
printf("Equal pointers.");
else
printf("Unequal pointers.");
return 0;
}