Mengapa array tidak dapat diteruskan sebagai argumen fungsi di C?

12

Mengikuti komentar ini , saya sudah mencoba ke google mengapa, tetapi google-fu saya gagal.

Komentar dari tautan:

[...] Tetapi yang penting adalah bahwa array dan pointer adalah hal yang berbeda dalam C.

Dengan anggapan Anda tidak menggunakan ekstensi kompiler, Anda umumnya tidak bisa meneruskan array itu sendiri ke suatu fungsi, tetapi Anda bisa melewatkan sebuah pointer, dan mengindeks sebuah pointer seolah-olah itu array.

Anda secara efektif mengeluh bahwa pointer tidak memiliki panjang terpasang. Anda harus mengeluh bahwa array tidak dapat dilewatkan sebagai argumen fungsi, atau array menurun ke pointer secara implisit.

Florian Margaine
sumber
Saya tidak yakin itu jawabannya, tetapi bagian dari jenis array adalah ukurannya, jadi saya yakin Anda harus mendefinisikan fungsi untuk setiap ukuran yang ingin Anda terima.
clcto
Apakah maksud Anda sebagai pointer fungsi ? Tolong jelaskan pertanyaannya.
user949300
2
@ user949300 Tidak, dari konteks komentar sudah cukup jelas; Anda tidak dapat melewatkan array ke suatu fungsi karena itu menjadi sebuah pointer, dan dia ingin tahu mengapa hal ini terjadi.
Doval
@DocBrown rlemon mengusulkan pengeditan untuk ini.
Florian Margaine

Jawaban:

18

Dugaan pertama saya untuk alasannya adalah semata-mata karena alasan kinerja dan penghematan memori, dan juga untuk kemudahan implementasi kompiler (terutama untuk jenis komputer pada saat C ditemukan). Melewati array besar "berdasarkan nilai" tampaknya memiliki dampak besar pada stack, perlu operasi copy array penuh untuk setiap pemanggilan fungsi, dan mungkin kompiler harus lebih pintar untuk menampilkan kode perakitan yang benar (meskipun poin terakhir masih bisa diperdebatkan) . Akan lebih sulit untuk memperlakukan array yang dialokasikan secara dinamis dengan cara yang sama dengan array yang dialokasikan secara statis (dari sudut pandang sintaksis bahasa).

EDIT: setelah membaca beberapa bagian dari link ini , saya pikir alasan sebenarnya (dan alasan mengapa array di structs diperlakukan sebagai jenis nilai, sedangkan array tunggal tidak) adalah kompatibilitas ke C pendahulunya B . Berikut ini kutipan dari Dennis Ritchie:

[...} Solusinya merupakan lompatan penting dalam rantai evolusi antara BCPL tanpa jenis dan mengetik C. Ini menghilangkan materialisasi dari pointer di penyimpanan, dan bukannya menyebabkan penciptaan pointer ketika nama array disebutkan dalam ekspresi. Aturan, yang bertahan dalam C hari ini, adalah bahwa nilai-nilai tipe array dikonversi, ketika mereka muncul dalam ekspresi, menjadi pointer ke yang pertama dari objek yang membentuk array.

Penemuan ini memungkinkan sebagian besar kode B yang ada untuk terus bekerja, meskipun ada perubahan mendasar dalam semantik bahasa. [..]

Doc Brown
sumber
5
A struct Foo { int array[N]; } dapat dilewati dengan nilai. Dan bit terakhir tentang memperlakukan alokasi dinamis dan statis sama nampak mencurigakan (sebuah array dalam arti ketat selalu mencakup ukuran, konsep pemersatu untuk hal-hal seperti array indexing adalah pointer digabungkan dengan peluruhan array-to-pointer), bisakah Anda menguraikan?
@ Darnan: Saya pikir prinsip-prinsip umum yang dinyatakan di sini adalah sehat. Jelas, jika Anda membungkus array Anda dalam sebuah struct, Anda menentukan maksud Anda. Dalam kasus umum, Anda hampir selalu melewati referensi.
Robert Harvey
Saya juga menemukan komentar yang direferensikan di OP tidak perlu bertele-tele. Jelas Anda melewati sebuah pointer daripada sebuah array dengan nilai. Apa yang sama benarnya adalah Anda secara efektif melewatkan array dengan referensi. Jika keberatannya adalah tidak ada panjang yang terpasang, cukup mudah untuk melewatinya juga.
Robert Harvey
@RobertHarvey Itu masih asimetri dalam sistem tipe: Semuanya melewati nilai, kecuali jenis array (meskipun array yang merupakan bagian dari tipe struct yang disahkan oleh nilai), dan bahkan menggunakan notasi yang sama persis (baik di situs panggilan dan dalam tanda tangan fungsi).
@ Darnan: Mengapa itu relevan, selain Anda harus mengingatnya?
Robert Harvey
9

Komputer mini PDP dengan hanya 8 kB memori tidak dapat mengalokasikan tumpukan yang sangat besar. Jadi, pada mesin seperti itu, seseorang harus berhati-hati dalam desain bahasa (atau evolusi) untuk dapat meminimalkan apa yang perlu dilakukan di stack untuk penggunaan panggilan subrutin umum yang diharapkan. C masih digunakan saat ini untuk memprogram sistem tertanam yang sangat terbatas memori (beberapa kB), sehingga trade-off biasanya bagus.

Pada arsitektur prosesor yang memiliki register sangat sedikit, melewatkan array dengan pointer daripada dengan nilai lebih sering memungkinkan register untuk digunakan sebagai optimasi panggilan subrutin.

hotpaw2
sumber
2
Saya memiliki beberapa papan yang memiliki 256 byte RAM untuk data dan 2K EEPROM untuk kode. Anda tidak ingin membuat salinan array di sana.
Jerry Jeremiah