Neden bir dizideki indeksleme 1'de değil C'de sıfır ile başlar?
Neden bir dizideki indeksleme 1'de değil C'de sıfır ile başlar?
Yanıtlar:
C'de, bir dizinin adı temelde bir işaretçi [ancak açıklamalara bakın] , bir bellek konumuna bir referanstır ve bu nedenle ifade , başlangıç öğesinden uzakta array[n]
bir bellek konumu n
öğelerine karşılık gelir . Bu, indeksin ofset olarak kullanıldığı anlamına gelir. Dizinin ilk öğesi, dizinin başvurduğu bellek konumunda tam olarak bulunur (0 öğe uzakta), bu nedenle olarak belirtilmelidir array[0]
.
Daha fazla bilgi için:
http://developeronline.blogspot.com/2008/04/why-array-index-should-start-from-0.html
sizeof arr
İşaretçinin boyutunu değil, dizi nesnesinin boyutunu verir.
sizeof
veya &
bir diziyi başlatmak için kullanılan bir dize değişmezi, türü olan bir ifade hariç " türünün ", dizi işaretçisinin
Bu soru bir yıldan fazla bir süre önce gönderildi, ama işte gidiyor ...
İken Dijkstra'nın makale (daha önce şimdi silinmiş başvurulan cevap ) matematiksel açıdan mantıklı, bu alakalı olarak değil de programlama gelince.
Dil belirtimi ve derleyici tasarımcıları tarafından alınan karar, bilgisayar sistemi tasarımcıları tarafından sayımı 0'da başlatma kararına dayanmaktadır.
Barış için bir savunmadan alıntı yapan Danny Cohen.
Herhangi bir b tabanı için, ilk b ^ N negatif olmayan tamsayılar yalnızca numaralandırma 0'dan başlıyorsa tam olarak N rakamıyla (baştaki sıfırlar dahil) temsil edilir .
Bu oldukça kolay bir şekilde test edilebilir. Taban-2'de, 2^3 = 8
8. sayı:
111
bir bit (4 bit) gerektirirken 3
, bitler kullanılarak temsil edilebilir 1000
.
Bilgisayar bellek adreslerinin bitlerle 2^N
adreslenmiş hücreleri vardır N
. Şimdi 1 olarak saymaya başlarsak, 2^N
hücrelerin N+1
adres satırlarına ihtiyacı olacaktır . Ekstra bit, tam olarak 1 adrese erişmek için gereklidir. ( 1000
yukarıdaki durumda.). Bunu çözmenin başka bir yolu, son adrese erişilemez bırakmak ve N
adres satırlarını kullanmak olacaktır .
Her ikisi de tam adres satırlarını kullanarak tüm adreslere erişilmesini sağlayacak 0'daki başlangıç sayımına kıyasla en uygun çözümlerdirN
!
0
Saymaya başlama kararı , o zamanlar üzerinde çalışan yazılımlar da dahil olmak üzere tüm dijital sistemlere nüfuz etmiştir, çünkü kodun temel sistemin yorumlayabileceği şeye çevrilmesini kolaylaştırır. Eğer böyle olmasaydı, her dizi erişimi için makine ve programlayıcı arasında gereksiz bir çeviri işlemi olurdu. Derlemeyi kolaylaştırır.
Makaleden alıntı:
a[b]
olduğu gibi uygulandı *(a+b)
. Bugün bile 2[a]
bunun yerine hala yazabilirsiniz a[2]
. Şimdi dizinler 0'dan başlamazsa a[b]
dönüşür *(a+b-1)
. Bu, 0 yerine zamanın CPU'larında 2 ekleme gerektiriyordu, yani hızın yarısı. Açıkçası arzu edilmez.
Çünkü 0, işaretçinin dizinin başına ve dizinin ilk öğesine ne kadar uzak olduğudur.
Düşünmek:
int foo[5] = {1,2,3,4,5};
0'a erişmek için:
foo[0]
Ancak foo bir işaretçiye ayrışır ve yukarıdaki erişim, ona erişen benzer işaretçi aritmetik yoluna sahiptir
*(foo + 0)
Bugünlerde işaretçi aritmetiği sık kullanılmamaktadır. Yine de, bir adres alıp X "ints" ı bu başlangıç noktasından uzaklaştırmanın uygun bir yoluydu. Tabii ki bulunduğunuz yerde kalmak istiyorsanız, 0 ekleyin!
0 tabanlı dizin izin verdiği için ...
array[index]
... uygulanacak ...
*(array + index)
Dizin 1 tabanlı olsaydı, derleyicinin şunu üretmesi gerekirdi: *(array + index - 1)
ve bu "-1" performansa zarar verirdi.
Çünkü derleyici ve bağlayıcıyı basitleştirdi (yazması daha kolay).
Referans :
"... Belleği bir adres ve ofset ile yönlendirmek neredeyse tüm bilgisayar mimarilerindeki donanımda doğrudan temsil edilir, bu nedenle C'deki bu tasarım detayı derlemeyi kolaylaştırır"
ve
“... bu daha basit bir uygulama sağlar ...”
Dizi dizini her zaman sıfır ile başlar, taban adresin 2000 olduğunu varsayalım arr[i] = *(arr+i)
. Şimdi if i= 0
, bu *(2000+0
) temel adrese veya dizideki ilk öğenin adresine eşittir. bu indeks ofset olarak kabul edilir, bu nedenle varsayılan indeks sıfırdan başlar.
Aynı nedenden ötürü, Çarşamba olduğunda ve birisi Çarşamba gününe kadar kaç gün sorarsa, 1 yerine 0 deyin ve Çarşamba olduğunda ve birisi Perşembe gününe kadar kaç gün, 2 yerine 1 deyin.
Sıfır tabanlı numaralandırma için okuduğum en zarif açıklama, değerlerin sayı satırındaki işaretli yerlerde değil, aralarındaki boşluklarda depolanmadığı gözlemidir. İlk öğe sıfır ile bir arasında, diğeri bir ile iki arasında vb. Saklanır. N'inci öğe N-1 ve N arasında saklanır. Bir öğe, her iki taraftaki sayılar kullanılarak açıklanabilir. Münferit kalemler, altındaki sayılar kullanılarak açıklanan konvansiyonladır. Birine bir aralık (X, Y) verilirse, aşağıdaki sayıyı kullanarak tek tek sayıları tanımlamak, herhangi bir aritmetik kullanmadan ilk öğeyi tanımlayabileceği anlamına gelir (X öğesi), ancak son öğeyi (Y) tanımlamak için Y'den bir tane çıkarmak gerekir. 1). Yukarıdaki sayıyı kullanarak öğeleri tanımlamak, bir aralıktaki son öğeyi tanımlamayı kolaylaştırır (Y öğesi olacaktır),
Öğeleri üstlerindeki sayıya göre tanımlamak korkunç olmasa da, aralıktaki ilk öğeyi (X, Y) X'in üstünde olan olarak tanımlamak genellikle onu aşağıdaki gibi tanımlamaktan daha iyi çalışır (X + 1).
Teknik neden, işaretçinin bir dizinin bellek konumuna gitmesinin, dizinin ilk öğesinin içeriği olması gerçeğinden kaynaklanabilir. İşaretçiyi bir indeksle bildirirseniz, programlar elbette istediğiniz şey olmayan içeriğe erişmek için normalde işaretçinin bir değerini işaretçiye ekler.
1 tabanlı bir matristeki X, Y koordinatlarını kullanarak bir piksel ekranına erişmeye çalışın. Formül tamamen karmaşıktır. Neden karmaşık? Çünkü X, Y koordinatlarını bir sayıya, ofsete dönüştürüyorsunuz. Neden X, Y'yi ofsete dönüştürmelisiniz? Çünkü bellek, bilgisayarlar içinde sürekli bir bellek hücresi akışı (diziler) olarak bu şekilde düzenlenir. Bilgisayarlar dizi hücreleriyle nasıl ilgilenir? Ofsetleri kullanma (ilk hücreden yer değiştirmeler, sıfır tabanlı bir indeksleme modeli).
Bu nedenle, kodun bir noktasında, 1 tabanlı formülü 0 tabanlı bir formüle dönüştürmek için ihtiyacınız olan (veya derleyicinin ihtiyacı olan), çünkü bilgisayarlar bellekle bu şekilde ilgilenir.
Diyelim ki 5 boyutlu bir dizi oluşturmak istiyoruz
diyelim
[5] = [2,3,5,9,8]
dizinin 1. öğesinin 100 konumuna işaret
etmesine izin verin ve dizin oluşturmanın 0.
Şimdi bir
elemanın
büyüklüğü 4-bit olduğu için 1. elementin konumunu indeks yardımıyla bulmalıyız (1. elementin konumunu hatırlayın)
-> indeks 1 dikkate alındığında pozisyon
boyut olacaktır (1) * tamsayı büyüklüğü (4) = 4,
böylece bize göstereceği gerçek konum
100 + 4 = 104
bu doğru değildir, çünkü başlangıç konumu 100'dür
. 104'e değil 100'e işaret etmelidir,
bu
şimdi yanlıştır , endekslemeyi 0'dan aldığımızı varsayalım,
sonra
1. elemanın konumu
indeks (0) * tamsayı büyüklüğü olmalıdır (4) = 0
bu nedenle ->
1. elemanın konumu 100 + 0 = 100'dür
ve elemanın gerçek konumu
buydu, bu yüzden indeksleme 0'dan başlar;
Umarım amacını temizler.
Java geçmişindeyim. Bu soruya, kendi kendini açıklayan bir kağıda yazdığım aşağıdaki diyagramda cevap verdim
Ana Adımlar:
Not : Resimde gösterilen bloklar bellek temsilidir
her şeyden önce, dizilerin dahili olarak işaretçiler olarak kabul edildiğini bilmeniz gerekir, çünkü "dizinin kendisi dizinin ilk öğesinin adresini içerir"
ex. int arr[2] = {5,4};
dizinin adres 100'de başladığını düşünün, böylece öğe ilk öğesi 100 adresinde ve ikinci şimdi 104'te olacaktır, dizi dizini 1'den başlarsa,
arr[1]:-
bu işaretçiler ifadesinde şöyle yazılabilir.
arr[1] = *(arr + 1 * (size of single element of array));
int boyutunu 4bayt olarak düşünün, şimdi,
arr[1] = *(arr + 1 * (4) );
arr[1] = *(arr + 4);
dizi adının ilk elemanının adresini içerdiğini bildiğimiz için şimdi arr = 100,
arr[1] = *(100 + 4);
arr[1] = *(104);
hangi verir,
arr[1] = 4;
Bu ifade nedeniyle, resmi ilk öğe olan 100 adresindeki öğeye erişemiyoruz,
Şimdi dizi dizininin 0'dan başladığını düşünün.
arr[0]:-
bu şu şekilde çözülecek
arr[0] = *(arr + 0 + (size of type of array));
arr[0] = *(arr + 0 * 4);
arr[0] = *(arr + 0);
arr[0] = *(arr);
şimdi, dizi adının ilk öğesinin adresini içerdiğini biliyoruz,
arr[0] = *(100);
doğru sonucu veren
arr[0] = 5;
bu nedenle dizi indeksi her zaman c'de 0'dan başlar.
kaynak: tüm detaylar "brian kerninghan ve dennis ritchie tarafından C programlama dili" kitabında yazılmıştır
Dizide, dizin başlangıç öğesinden uzaklığı söyler. Bu nedenle, ilk eleman başlangıç elemanından 0 uzaklıktadır. Bu yüzden dizi 0'dan başlar.
Bunun nedeni , dizide address
sağa işaret etmesi gerektiğidir element
. Aşağıdaki diziyi varsayalım:
let arr = [10, 20, 40, 60];
Şimdi adres varlığın başlangıcını ele alalım 12
ve boyutunu element
yönelik olacaktır 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
Eğer öyle olsaydı değil zero-based
, teknik olarak bizim ilk öğesi adres array
olacaktır 16
's konum olarak yanlıştır 12
.
Dizi adı, temel adrese işaret eden sabit bir işaretçidir. Arr [i] kullandığınızda derleyici bunu * (arr + i) olarak değiştirir. İnt aralığı -128 ila 127 olduğu için, derleyici -128 ila -1 arasında olduğunu düşünür. negatif sayılar ve 0 ila 128 arasında pozitif sayılar olduğundan dizi dizini her zaman sıfır ile başlar.
int
En az 16 bitlik bir aralığı desteklemek için bir tür gereklidir ve çoğu sistemde bu gün 32 biti desteklemektedir. Bence mantığınız kusurlu ve cevabınız diğer insanlar tarafından verilen diğer cevaplarda gerçekten düzelmiyor. Bunu silmenizi öneririm.