Inilah pendapat saya:
Pengembangan Bahasa C menawarkan beberapa wawasan tentang evolusi tipe array di C:
Saya akan mencoba menguraikan hal array:
Pendahulu C B dan BCPL tidak memiliki tipe larik yang berbeda, deklarasi seperti:
auto V[10] (B)
or
let V = vec 10 (BCPL)
akan mendeklarasikan V sebagai pointer (tanpa tipe) yang diinisialisasi untuk menunjuk ke wilayah 10 "kata" memori yang tidak digunakan. B sudah digunakan *
untuk pointer dereferencing dan memiliki []
notasi tangan pendek, *(V+i)
dimaksudkan V[i]
, seperti di C / C ++ hari ini. Bagaimanapun, V
ini bukanlah sebuah array, itu masih sebuah pointer yang menunjuk ke beberapa memori. Ini menimbulkan masalah ketika Dennis Ritchie mencoba memperpanjang B dengan tipe struct. Dia ingin array menjadi bagian dari struct, seperti di C hari ini:
struct {
int inumber;
char name[14];
};
Tetapi dengan konsep array B, BCPL sebagai pointer, ini akan membutuhkan name
field untuk memuat pointer yang harus diinisialisasi pada saat runtime ke wilayah memori 14 byte dalam struct. Masalah inisialisasi / tata letak pada akhirnya diselesaikan dengan memberikan perlakuan khusus kepada array: Kompilator akan melacak lokasi array dalam struktur, di tumpukan, dll. Tanpa benar-benar memerlukan penunjuk ke data untuk terwujud, kecuali dalam ekspresi yang melibatkan array. Perlakuan ini memungkinkan hampir semua kode B untuk tetap berjalan dan merupakan sumber dari aturan "larik dikonversi ke penunjuk jika Anda melihatnya" . Ini adalah peretasan kompatibilitas, yang ternyata sangat berguna, karena memungkinkan array berukuran terbuka, dll.
Dan inilah tebakan saya mengapa array tidak dapat ditetapkan: Karena array adalah pointer di B, Anda cukup menulis:
auto V[10];
V=V+5;
untuk me-rebase sebuah "array". Ini sekarang tidak ada artinya, karena basis variabel array bukan lagi nilai l. Jadi tugas ini tidak diizinkan, yang membantu menangkap beberapa program yang melakukan pemeringkatan ini pada array yang dideklarasikan. Dan kemudian gagasan ini macet: Karena array tidak pernah dirancang untuk menjadi kelas pertama yang dikutip dari sistem tipe C, mereka kebanyakan diperlakukan sebagai binatang khusus yang menjadi penunjuk jika Anda menggunakannya. Dan dari sudut pandang tertentu (yang mengabaikan bahwa C-array adalah hack yang gagal), pelarangan penetapan array masih masuk akal: Array terbuka atau parameter fungsi array diperlakukan sebagai penunjuk tanpa informasi ukuran. Kompilator tidak memiliki informasi untuk menghasilkan penetapan larik untuk mereka dan penugasan penunjuk diperlukan untuk alasan kompatibilitas.
typedef int vec[3];
void f(vec a, vec b)
{
vec x,y;
a=b;
x=y;
a=x;
x=a;
}
Ini tidak berubah ketika revisi C pada tahun 1978 menambahkan penetapan struct ( http://cm.bell-labs.com/cm/cs/who/dmr/cchanges.pdf ). Meskipun record adalah tipe yang berbeda di C, itu tidak mungkin untuk menetapkannya di awal K&R C. Anda harus menyalinnya dari segi anggota dengan memcpy dan Anda hanya dapat meneruskan pointer ke mereka sebagai parameter fungsi. Assigment (dan parameter passing) sekarang hanya didefinisikan sebagai memcpy dari memori mentah struct dan karena ini tidak dapat merusak kode yang sudah ada, maka dengan mudah diadpot. Sebagai efek samping yang tidak disengaja, ini secara implisit memperkenalkan beberapa jenis penugasan array, tetapi ini terjadi di suatu tempat di dalam struktur, jadi ini tidak bisa benar-benar memperkenalkan masalah dengan cara array digunakan.