Pertama, berikut adalah beberapa kode:
int main()
{
int days[] = {1,2,3,4,5};
int *ptr = days;
printf("%u\n", sizeof(days));
printf("%u\n", sizeof(ptr));
return 0;
}
Apakah ada cara untuk mengetahui ukuran array yang ptr
menunjuk (bukan hanya memberikan ukurannya, yaitu empat byte pada sistem 32-bit)?
Jawaban:
Tidak bisa. Compiler tidak tahu apa yang menunjuk pointer. Ada trik, seperti mengakhiri array dengan nilai out-of-band yang diketahui dan kemudian menghitung ukuran hingga nilai itu, tetapi itu tidak menggunakan
sizeof()
.Trik lain adalah yang disebutkan oleh Zan , yaitu menyembunyikan ukuran di suatu tempat. Misalnya, jika Anda secara dinamis mengalokasikan array, alokasikan satu blok int lebih besar dari yang Anda butuhkan, simpan ukuran di int pertama, dan kembali
ptr+1
sebagai penunjuk ke array. Saat Anda membutuhkan ukuran, kurangi pointer dan intip pada nilai simpanan. Ingatlah untuk membebaskan seluruh blok mulai dari awal, dan bukan hanya array.sumber
Jawabannya adalah tidak."
Apa yang programmer C lakukan adalah menyimpan ukuran array di suatu tempat. Ini bisa menjadi bagian dari struktur, atau programmer dapat menipu sedikit dan
malloc()
lebih banyak memori daripada yang diminta untuk menyimpan nilai panjang sebelum dimulainya array.sumber
Untuk array dinamis ( malloc atau C ++ baru ), Anda perlu menyimpan ukuran array seperti yang disebutkan oleh orang lain atau mungkin membangun struktur manajer array yang menangani menambah, menghapus, menghitung, dll. Sayangnya C tidak melakukan ini hampir sebaik C ++ karena pada dasarnya Anda harus membangunnya untuk setiap jenis array berbeda yang Anda simpan yang rumit jika Anda memiliki beberapa jenis array yang perlu Anda kelola.
Untuk array statis, seperti yang ada di contoh Anda, ada makro umum yang digunakan untuk mendapatkan ukuran, tetapi tidak disarankan karena tidak memeriksa apakah parameternya benar-benar array statis. Makro digunakan dalam kode nyata, misalnya dalam header kernel Linux meskipun mungkin sedikit berbeda dari yang di bawah ini:
Anda dapat google karena alasan untuk waspada terhadap makro seperti ini. Hati-hati.
Jika memungkinkan, stdlib C ++ seperti vektor yang jauh lebih aman dan lebih mudah digunakan.
sumber
ARRAY_SIZE
makro selalu bekerja jika argumen adalah array (yaitu ekspresi tipe array). Untuk apa yang disebut "array dinamis", Anda tidak pernah mendapatkan "array" yang sebenarnya (ekspresi tipe array). (Tentu saja, Anda tidak bisa, karena tipe array menyertakan ukurannya pada waktu kompilasi.) Anda hanya mendapatkan pointer ke elemen pertama. Keberatan Anda "tidak memeriksa apakah parameternya benar-benar array statis" tidak benar-benar valid, karena mereka berbeda karena satu adalah array dan yang lainnya tidak.Ada solusi bersih dengan templat C ++, tanpa menggunakan sizeof () . Fungsi getSize () berikut mengembalikan ukuran array statis apa pun:
Berikut ini adalah contoh dengan struktur foo_t :
Keluaran:
sumber
T (&)[SIZE]
. Bisakah Anda menjelaskan apa artinya ini? Anda juga bisa menyebutkan constexpr dalam konteks ini.SIZE
sebagai argumen, itu adalah param templat yang memiliki sudah diketahui oleh definisi fungsi.)Untuk contoh khusus ini, ya, ada, JIKA Anda menggunakan typedefs (lihat di bawah). Tentu saja, jika Anda melakukannya dengan cara ini, Anda sebaiknya menggunakan SIZEOF_DAYS, karena Anda tahu apa yang ditunjukkan oleh pointer.
Jika Anda memiliki pointer (void *), seperti yang dikembalikan oleh malloc () atau sejenisnya, maka, tidak, tidak ada cara untuk menentukan struktur data apa yang menunjuk pointer dan dengan demikian, tidak ada cara untuk menentukan ukurannya.
Keluaran:
sumber
Karena semua jawaban yang benar telah dinyatakan, Anda tidak bisa mendapatkan informasi ini hanya dari nilai pointer yang rusak dari array. Jika pembusukan pointer adalah argumen yang diterima oleh fungsi, maka ukuran array yang berasal harus disediakan dalam beberapa cara lain agar fungsi mengetahui ukuran itu.
Berikut adalah saran yang berbeda dari apa yang telah disediakan sejauh ini, yang akan berfungsi: Lewati sebuah pointer ke array. Saran ini mirip dengan saran gaya C ++, kecuali bahwa C tidak mendukung templat atau referensi:
Tapi, saran ini agak konyol untuk masalah Anda, karena fungsi ini didefinisikan untuk mengetahui persis ukuran array yang dilewatkan (karenanya, ada sedikit kebutuhan untuk menggunakan sizeof sama sekali pada array). Apa yang dilakukannya adalah menawarkan beberapa tipe keamanan. Ini akan melarang Anda untuk melewati array dengan ukuran yang tidak diinginkan.
Jika fungsi tersebut seharusnya dapat beroperasi pada berbagai ukuran array, maka Anda harus memberikan ukuran pada fungsi sebagai informasi tambahan.
sumber
Tidak ada solusi ajaib. C bukan bahasa reflektif. Objek tidak secara otomatis tahu apa itu.
Tetapi Anda memiliki banyak pilihan:
sumber
Solusi saya untuk masalah ini adalah menyimpan panjang array ke dalam array Array sebagai meta-informasi tentang array.
Tetapi Anda harus peduli mengatur panjang array yang tepat yang ingin Anda simpan, karena tidak ada cara untuk memeriksa panjang ini, seperti yang dijelaskan teman-teman kami secara besar-besaran.
sumber
Anda dapat melakukan sesuatu seperti ini:
sumber
Tidak, Anda tidak dapat menggunakan
sizeof(ptr)
untuk menemukan ukuran arrayptr
yang menunjuk.Meskipun mengalokasikan memori ekstra (lebih dari ukuran array) akan sangat membantu jika Anda ingin menyimpan panjang di ruang ekstra.
sumber
Ukuran hari [] adalah 20 yang bukan dari elemen * ukuran tipe datanya. Sementara ukuran pointer adalah 4 tidak peduli apa yang menunjuk. Karena sebuah pointer menunjuk ke elemen lain dengan menyimpan alamatnya.
sumber
array_size diteruskan ke variabel ukuran :
Penggunaannya adalah:
sumber
Dalam string ada
'\0'
karakter di akhir sehingga panjang string bisa didapat menggunakan fungsi sepertistrlen
. Masalah dengan array integer, misalnya, adalah bahwa Anda tidak dapat menggunakan nilai apa pun sebagai nilai akhir sehingga salah satu solusi yang mungkin adalah mengatasi array dan menggunakan nilai akhir sebagaiNULL
penunjuk.sumber
NULL
mungkin adalah alternatif yang paling efisien yang bisa dibayangkan dengan hanya menyimpan yang terpisahsize
secara langsung. Terutama jika Anda benar-benar menggunakan lapisan tipuan ekstra ini sepanjang waktu.