Mengapa pengindeksan dalam array dimulai dengan nol dalam C dan bukan dengan 1?
Mengapa pengindeksan dalam array dimulai dengan nol dalam C dan bukan dengan 1?
Jawaban:
Dalam C, nama array pada dasarnya adalah sebuah pointer [tetapi lihat komentar] , referensi ke lokasi memori, dan dengan demikian ekspresi array[n]merujuk ke nelemen lokasi memori jauh dari elemen awal. Ini berarti bahwa indeks digunakan sebagai offset. Elemen pertama dari array persis terkandung di lokasi memori yang merujuk (0 elemen), sehingga harus dilambangkan sebagai array[0].
Untuk info lebih lanjut:
http://developeronline.blogspot.com/2008/04/why-array-index-should-start-from-0.html
sizeof arrmenghasilkan ukuran objek array, bukan ukuran pointer.
sizeofoperator, atau &operator unary , atau string literal yang digunakan untuk menginisialisasi array, ekspresi yang memiliki tipe" array tipe "dikonversi ke ekspresi dengan tipe" pointer to type "yang menunjuk ke elemen awal objek array dan bukan nilai. Jika objek array memiliki kelas penyimpanan terdaftar, perilaku tidak ditentukan. "
Pertanyaan ini diposting lebih dari setahun yang lalu, tetapi begini ...
Sementara artikel Dijkstra (sebelumnya dirujuk dalam jawaban yang sekarang dihapus ) masuk akal dari perspektif matematika, itu tidak relevan ketika datang ke pemrograman.
Keputusan yang diambil oleh spesifikasi bahasa & perancang-kompiler didasarkan pada keputusan yang dibuat oleh perancang sistem komputer untuk mulai menghitung pada 0.
Mengutip dari Permohonan Damai oleh Danny Cohen.
Untuk setiap basis b, b ^ N pertama bilangan bulat non-negatif diwakili oleh digit N persis (termasuk nol di depan) hanya jika penomoran dimulai pada 0.
Ini dapat diuji dengan cukup mudah. Di base-2, ambil 2^3 = 8
nomor 8 adalah:
111dapat direpresentasikan menggunakan 3bit, sementara 1000akan membutuhkan bit tambahan (4 bit).
Alamat memori komputer memiliki 2^Nsel yang ditangani oleh Nbit. Sekarang jika kita mulai menghitung pada 1, 2^Nsel akan membutuhkan N+1garis alamat. Bit ekstra diperlukan untuk mengakses tepat 1 alamat. ( 1000dalam kasus di atas.). Cara lain untuk menyelesaikannya adalah meninggalkan alamat terakhir tidak dapat diakses, dan menggunakan Nbaris alamat.
Keduanya merupakan solusi sub-optimal , dibandingkan dengan penghitungan mulai pada 0, yang akan membuat semua alamat dapat diakses, menggunakan Ngaris alamat yang tepat !
Keputusan untuk mulai menghitung 0, sejak itu meresapi semua sistem digital , termasuk perangkat lunak yang menjalankannya, karena membuatnya lebih mudah bagi kode untuk menerjemahkan apa yang dapat ditafsirkan oleh sistem yang mendasarinya. Jika tidak, akan ada satu operasi terjemahan yang tidak perlu antara mesin dan pemrogram, untuk setiap akses array. Itu membuat kompilasi lebih mudah.
Mengutip dari kertas:

a[b]diimplementasikan seperti *(a+b)pada kompiler awal. Bahkan saat ini Anda masih dapat menulis 2[a]bukan a[2]. Sekarang jika indeks tidak dimulai pada 0 maka a[b]akan berubah menjadi *(a+b-1). Ini akan membutuhkan 2 tambahan pada CPU pada waktu bukan 0, yang berarti setengah dari kecepatan. Jelas tidak diinginkan.
Karena 0 adalah seberapa jauh dari pointer ke kepala array ke elemen pertama array.
Mempertimbangkan:
int foo[5] = {1,2,3,4,5};
Untuk mengakses 0 kami lakukan:
foo[0]
Tapi foo terurai menjadi pointer, dan akses di atas memiliki cara aritmatika pointer analog untuk mengaksesnya
*(foo + 0)
Aritmatika penunjuk hari ini tidak sering digunakan. Namun ketika masih jauh, itu adalah cara yang mudah untuk mengambil alamat dan memindahkan X "ints" dari titik awal. Tentu saja jika Anda ingin tetap di tempat Anda sekarang, Anda tinggal menambahkan 0!
Karena indeks berbasis 0 memungkinkan ...
array[index]
... untuk diimplementasikan sebagai ...
*(array + index)
Jika indeks berbasis 1, kompiler harus menghasilkan:, *(array + index - 1)dan "-1" ini akan merusak kinerja.
Karena itu membuat kompiler dan linker lebih sederhana (lebih mudah untuk menulis).
"... Mengacu memori dengan alamat dan offset diwakili langsung dalam perangkat keras pada hampir semua arsitektur komputer, jadi detail desain ini di C membuat kompilasi lebih mudah"
dan
"... ini membuat implementasi yang lebih sederhana ..."
Indeks array selalu dimulai dengan nol. Mari kita asumsikan alamat basis adalah 2000. Sekarang arr[i] = *(arr+i). Sekarang if i= 0, ini berarti *(2000+0) sama dengan alamat dasar atau alamat elemen pertama dalam array. indeks ini diperlakukan sebagai offset, sehingga indeks bydeafault dimulai dari nol.
Untuk alasan yang sama bahwa, ketika hari Rabu dan seseorang bertanya berapa hari sampai hari Rabu, Anda mengatakan 0 daripada 1, dan bahwa ketika hari Rabu dan seseorang bertanya berapa hari hingga Kamis, Anda mengatakan 1 daripada 2.
Penjelasan paling elegan yang pernah saya baca untuk penomoran berbasis nol adalah pengamatan bahwa nilai-nilai tidak disimpan di tempat-tempat yang ditandai pada garis bilangan, melainkan di ruang di antara mereka. Item pertama disimpan antara nol dan satu, item berikutnya antara satu dan dua, dll. Item N disimpan di antara N-1 dan N. Berbagai item dapat dijelaskan menggunakan angka-angka di kedua sisi. Masing-masing item berdasarkan konvensi dijelaskan menggunakan angka-angka di bawahnya. Jika seseorang diberi rentang (X, Y), mengidentifikasi nomor individual menggunakan angka di bawah ini berarti bahwa seseorang dapat mengidentifikasi item pertama tanpa menggunakan aritmatika (itu item X) tetapi seseorang harus mengurangi satu dari Y untuk mengidentifikasi item terakhir (Y -1). Mengidentifikasi item menggunakan nomor di atas akan membuatnya lebih mudah untuk mengidentifikasi item terakhir dalam suatu rentang (itu akan menjadi item Y),
Meskipun tidak akan mengerikan untuk mengidentifikasi item berdasarkan nomor di atasnya, mendefinisikan item pertama dalam rentang (X, Y) sebagai item di atas X umumnya bekerja lebih baik daripada mendefinisikannya sebagai yang di bawah ini (X + 1).
Alasan teknis mungkin berasal dari fakta bahwa penunjuk ke lokasi memori array adalah isi dari elemen pertama array. Jika Anda mendeklarasikan pointer dengan indeks satu, program biasanya akan menambahkan nilai itu ke pointer untuk mengakses konten yang bukan yang Anda inginkan, tentu saja.
Cobalah untuk mengakses layar piksel menggunakan koordinat X, Y pada matriks berbasis 1. Rumusnya sangat kompleks. Mengapa rumit? Karena Anda akhirnya mengonversi koordinat X, Y menjadi satu angka, offset. Mengapa Anda perlu mengonversi X, Y ke offset? Karena itulah cara memori diatur di dalam komputer, sebagai aliran sel memori (array) yang berkelanjutan. Bagaimana komputer menangani sel array? Menggunakan offset (perpindahan dari sel pertama, model pengindeksan berbasis nol).
Jadi pada titik tertentu dalam kode yang Anda butuhkan (atau kebutuhan kompilator) untuk mengubah rumus 1-basis menjadi rumus berbasis 0 karena itulah cara komputer menangani memori.
Misalkan kita ingin membuat array dengan ukuran 5
int array [5] = [2,3,5,9,8]
mari elemen pertama dari array diarahkan ke lokasi 100
dan mari kita pertimbangkan pengindeksan dimulai dari 1 bukan dari 0.
sekarang kita harus menemukan lokasi elemen 1 dengan bantuan indeks
(ingat lokasi elemen 1 adalah 100)
karena ukuran bilangan bulat adalah 4-bit
karena itu -> dengan mempertimbangkan indeks 1 posisi akan menjadi
ukuran of index (1) * size of integer (4) = 4
sehingga posisi aktual yang akan ditunjukkan kepada kita adalah
100 + 4 = 104
yang tidak benar karena lokasi awal berada pada 100.
seharusnya menunjuk ke 100 bukan pada 104
ini salah
sekarang misalkan kita telah mengambil pengindeksan dari 0
maka
posisi elemen 1 harus
ukuran indeks (0) * ukuran bilangan bulat (4) = 0
karena itu ->
lokasi elemen 1 adalah 100 + 0 = 100
dan itu adalah lokasi sebenarnya dari elemen
ini mengapa pengindeksan dimulai pada 0;
Saya harap ini akan menjelaskan maksud Anda.
Saya dari latar belakang Java. Saya telah mempresentasikan jawaban untuk pertanyaan ini dalam diagram di bawah ini yang telah saya tulis di selembar kertas yang cukup jelas
Langkah Utama:
Catatan : Blok yang ditunjukkan pada gambar adalah representasi memori
pertama-tama Anda perlu tahu bahwa array secara internal dianggap sebagai pointer karena "nama array itu sendiri berisi alamat elemen pertama array"
ex. int arr[2] = {5,4};
pertimbangkan bahwa array dimulai pada alamat 100 sehingga elemen elemen pertama akan di alamat 100 dan yang kedua akan berada di 104 sekarang, pertimbangkan bahwa jika indeks array dimulai dari 1, maka
arr[1]:-
ini dapat ditulis dalam ekspresi pointer seperti ini-
arr[1] = *(arr + 1 * (size of single element of array));
pertimbangkan ukuran int adalah 4bytes, sekarang,
arr[1] = *(arr + 1 * (4) );
arr[1] = *(arr + 4);
seperti yang kita ketahui nama array berisi alamat elemen pertama sehingga arr = 100 sekarang,
arr[1] = *(100 + 4);
arr[1] = *(104);
pemberian yang mana,
arr[1] = 4;
karena ungkapan ini kami tidak dapat mengakses elemen di alamat 100 yang merupakan elemen pertama resmi,
sekarang pertimbangkan indeks array mulai dari 0, jadi
arr[0]:-
ini akan diselesaikan sebagai
arr[0] = *(arr + 0 + (size of type of array));
arr[0] = *(arr + 0 * 4);
arr[0] = *(arr + 0);
arr[0] = *(arr);
sekarang, kita tahu bahwa nama array mengandung alamat elemen pertamanya jadi,
arr[0] = *(100);
yang memberikan hasil yang benar
arr[0] = 5;
Oleh karena itu indeks array selalu dimulai dari 0 di c.
referensi: semua detail ditulis dalam buku "Bahasa pemrograman C oleh brian kerninghan dan dennis ritchie"
Dalam array, indeks memberi tahu jarak dari elemen awal. Jadi, elemen pertama berjarak 0 dari elemen awal. Jadi, itu sebabnya array mulai dari 0.
Itu karena addressharus menunjuk ke kanan elementdalam array. Mari kita asumsikan array di bawah ini:
let arr = [10, 20, 40, 60];
Mari kita mempertimbangkan awal keberadaan alamat 12dan ukuran elementbe 4 bytes.
address of arr[0] = 12 + (0 * 4) => 12
address of arr[1] = 12 + (1 * 4) => 16
address of arr[2] = 12 + (2 * 4) => 20
address of arr[3] = 12 + (3 * 4) => 24
Jika itu tidak zero-based , secara teknis alamat elemen pertama kami di arrayakan 16yang salah karena lokasi itu adalah 12.
Nama array adalah pointer konstan yang menunjuk ke alamat basis. Ketika Anda menggunakan arr [i] kompiler memanipulasi sebagai * (arr + i). Karena kisaran int adalah -128 hingga 127, kompiler berpikir bahwa -128 ke -1 adalah angka negatif dan 0 hingga 128 adalah angka positif. Jadi indeks array selalu dimulai dengan nol.
intDiperlukan suatu jenis untuk mendukung setidaknya kisaran 16-bit, dan pada kebanyakan sistem dewasa ini mendukung 32-bit. Saya pikir logika Anda cacat, dan jawaban Anda benar-benar tidak meningkat pada jawaban lain yang sudah disediakan oleh orang lain. Saya sarankan menghapus ini.