Array dan pointer bukan hal yang sama dalam C, meskipun mereka terkait dan dapat digunakan dengan cara yang sama. Sejauh ini kita semua sepakat.
Namun, saya tidak melihat mengapa array dimasukkan dalam C, ketika pointer bisa melakukan pekerjaan mereka dengan sempurna.
Saya tidak mengatakan untuk menghapus notasi array (misalnya, a [5] atau int a [4] = {0,1,2,3};), yang cukup berguna dan nyaman. Tetapi Anda dapat memiliki notasi yang sama bekerja di atas pointer (seperti halnya), sebagai ukuran kosmetik. Jadi notasi array bukan alasan untuk memiliki array, hanya notasi!
Satu-satunya perbedaan yang saya lihat adalah array adalah pointer konstan, dan ukuran memori yang mereka tunjuk tidak dapat diubah. Tapi ini bisa dicapai dengan pointer juga, tepatnya dengan membuatnya konstan (memori tidak akan berukuran tetap, tapi saya tidak yakin apakah ini masalah).
Jadi mengapa tidak hanya memiliki pointer dan biarkan programmer memutuskan bagaimana pointer harus berperilaku (yaitu, konstan, bukan konstan, ukuran tetap, ukuran variabel, dll)?
x = a + b * 2;
ketika Anda dapat mencapai hal yang sama dengan urutan ekspresi sederhana sepertix = b; x*=2; x+=a;
?Jawaban:
Array adalah memori yang berdekatan yang dibuat pada stack. Anda tidak dapat menjamin memori tumpukan berdekatan tanpa gula sintaksis ini, dan bahkan jika Anda bisa, Anda harus mengalokasikan pointer terpisah untuk dapat melakukan aritmatika pointer (kecuali jika Anda ingin melakukannya
*(&foo + x)
, yang saya tidak tentu tetapi itu mungkin melanggar semantik nilai-l, tetapi setidaknya cukup canggung, dan akan berteriak untuk semacam gula sintaksis). Dari segi desain, ini juga merupakan bentuk enkapsulasi, karena Anda dapat merujuk ke koleksi dengan pengenal tunggal (yang jika tidak akan memerlukan pointer terpisah). Dan bahkan jika Anda dapat mengalokasikannya secara berdekatan dan mengalokasikan pointer terpisah untuk referensi mereka, Anda akan memiliki salah satuint fooForSomething, fooForSomethingElse
... yang memaksa cukup banyak kreativitas ketika koleksi Anda tumbuh, sehingga Anda mungkin berpikir untuk menyederhanakan denganint foo1, foo2
..., yang terlihat seperti array tetapi lebih sulit untuk dipertahankan.sumber
static
S) biasanya berakhir di tempat lain tergantung pada lingkungan.Notasi array nyaman, lebih mudah dibaca, dan lebih rentan terhadap kesalahan. Ini memberikan formalisme atas petunjuk. Ini mungkin gula sintaksis, tetapi kita semua perlu sedikit rasa manis sesekali, bukan?
Seperti halnya semua abstraksi, Anda memberikan sedikit fleksibilitas untuk kenyamanan yang disediakan abstraksi.
sumber
Saya terkejut bahwa belum ada yang berkomentar tentang array multidimensi.
Jika Anda memiliki matriks yang terbuat dari "nested pointer" (katakanlah
int **p
) apa yang Anda miliki di setiap "baris" (dimensi luar) adalah pointer yang menunjuk ke elemen pertama di baris itu, sehingga mengakses suatu nilai memerlukan dua akses memori. Plus, memori yang dibutuhkan adalahsizeof(*int)*n + n*m*sizeof(int)
.Dalam skenario array dua dimensi
int p[n][m]
, mengakses elemen hanya membutuhkan satu akses memori, karena alamat baris dihitung daripada melihat ke atas; dan memori yang dibutuhkan adalah adiln*m*sizeof(int)
.Tempat lain di mana array tidak dapat diganti oleh pointer adalah struktur di dalamnya.
secara definitif tidak sama dengan
ukuran array penting di sana, dan pointer tidak memiliki informasi itu.
Jadi ya, array unidimensional dan pointer tunggal sebagian besar dapat dipertukarkan, tetapi kesamaan mereka berakhir di sana.
sumber
i,j
dengani*cols+j
, tetapi saya pikir tidak harus melakukannya sendiri adalah alasan yang cukup baik untuk membenarkan keberadaan tipe array.Mengapa saya ingin tidak dapat menggunakan array untuk tipe nilai?
int a[4] = {0,1,2,3};
sumber
Bagaimana Anda menangani platform, seperti 8031 tanpa memori eksternal, yang tidak mendukung
malloc
ataualloca
? Mungkin Anda lupa bahwa C tidak hanya untuk setrika besar tetapi juga untuk pengontrol elevator dan pemanggang roti.sumber
Dalam C, notasi array dalam ekspresi selalu hanya pointer aritmatika. Semua penggunaan pengidentifikasi array dalam ekspresi segera dikonversi dari "array T" ke "pointer ke T" dan nilainya dikonversi ke pointer ke elemen pertama array. Notasi array (misalnya
a[1][2]
) selalu diperluas menjadi aritmatika pointer (misalnya*(*(t+1)+2)
).Namun notasi array dalam deklarasi dan definisi adalah sesuatu yang sepenuhnya berbeda. Sebuah declarator Array menggambarkan "array T " jenis di mana nilai-nilai jenis ini adalah urutan dari elemen tipe T . Definisi objek array adalah semua tentang menggunakan notasi array yang mudah dan mudah dipahami untuk mengalokasikan jumlah penyimpanan yang sesuai untuk objek array yang diinginkan sedemikian rupa sehingga pengidentifikasi array merujuk ke penyimpanan ini tanpa terlihat seperti pointer. Akibatnya notasi array dalam deklarasi atau definisi adalah makro yang menghasilkan ekspresi menggunakan
sizeof()
dan aritmatika, dan dalam kasus definisi, setara denganalloca()
untuk array otomatis atau yang setara di linker untuk array global, dan melakukan semuanya pada waktu kompilasi (baik kecuali untuk array panjang variabel C99).Penggunaan notasi array dalam ekspresi dan penggunaan tipe array tidak begitu terhubung, meskipun itu adalah tradisi dan idiom untuk menggunakan notasi array dalam ekspresi untuk referensi penyimpanan dalam objek yang dideklarasikan dan / atau didefinisikan sebagai array. Anda dapat dengan mudah menggunakan notasi array dengan tipe pointer untuk membuat pointer aritmatika lebih bersih dan lebih bermakna. Memang dalam C ekspresi bentuk
e1[e2]
persis sama dengan ekspresi*((e1)+(e2))
. Biasa konversi biner diterapkan pada dua operan, dan hasilnya selalu merupakan lvalue . Karena operator tidak langsung (*
) harus memiliki penunjuk sebagai operan, salah satu darie1
dane2
harus menjadi penunjuk dan yang lainnya harus bilangan bulat, tetapi tidak masalahkarena konversi unary awal untuk setiap "array T" adalah mengubahnya menjadi "pointer ke T". Notasi array dalam ekspresi pada dasarnya adalah kompiler (tingkat bahasa) makro untuk menghasilkan ekspresi aritmatika pointer.Jadi sebenarnya C sudah berfungsi seperti yang Anda sarankan, tetapi Anda membingungkan penggunaan notasi dalam dua konteks yang sangat terpisah.
sumber