Warum beginnt die Indizierung in einem Array mit Null in C und nicht mit 1?
Warum beginnt die Indizierung in einem Array mit Null in C und nicht mit 1?
Antworten:
In C ist der Name eines Arrays im Wesentlichen ein Zeiger [siehe jedoch die Kommentare] , ein Verweis auf einen Speicherort, und daher array[n]bezieht sich der Ausdruck auf einen Speicherort, der vom nStartelement entfernt ist. Dies bedeutet, dass der Index als Offset verwendet wird. Das erste Element des Arrays ist genau in dem Speicherort enthalten, auf den sich das Array bezieht (0 Elemente entfernt), daher sollte es als bezeichnet werden array[0].
Für mehr Information:
http://developeronline.blogspot.com/2008/04/why-array-index-should-start-from-0.html
sizeof arrGibt die Größe des Array-Objekts an, nicht die Größe eines Zeigers.
sizeofOperators oder den unären &Operator handelt oder um ein Zeichenfolgenliteral, das zum Initialisieren eines Arrays verwendet wird, eines Ausdrucks vom Typ" Array " vom Typ "wird in einen Ausdruck mit dem Typ" Zeiger auf Typ "konvertiert, der auf das Anfangselement des Array-Objekts zeigt und kein Wert ist. Wenn das Array-Objekt eine Registerspeicherklasse hat, ist das Verhalten undefiniert. "
Diese Frage wurde vor über einem Jahr gestellt, aber hier geht ...
Während Dijkstras Artikel (auf den zuvor in einer jetzt gelöschten Antwort verwiesen wurde ) aus mathematischer Sicht sinnvoll ist, ist er für die Programmierung nicht so relevant .
Die Entscheidung der Sprachspezifikation und der Compiler-Designer basiert auf der Entscheidung der Computersystem-Designer, mit der Zählung bei 0 zu beginnen.
Zitat aus einem Plädoyer für Frieden von Danny Cohen.
Für jede Basis b werden die ersten nicht negativen Ganzzahlen b ^ N nur dann durch genau N Ziffern (einschließlich führender Nullen) dargestellt, wenn die Nummerierung bei 0 beginnt.
Dies kann recht einfach getestet werden. Nehmen Sie in Basis 2 die 2^3 = 8
8. Zahl:
111kann mit 3Bits dargestellt werden, 1000erfordert jedoch ein zusätzliches Bit (4 Bits).
Computerspeicheradressen haben 2^NZellen, die durch NBits adressiert sind . Wenn wir jetzt bei 1 zählen, 2^Nbenötigen N+1die Zellen Adressleitungen. Das Extra-Bit wird benötigt, um auf genau 1 Adresse zuzugreifen. ( 1000im obigen Fall.) Eine andere Möglichkeit, dies zu lösen, besteht darin, die letzte Adresse nicht zugänglich zu lassen und NAdresszeilen zu verwenden.
Beides sind suboptimale Lösungen im Vergleich zur Startzählung bei 0, bei der alle Adressen über exakte NAdresszeilen zugänglich bleiben !
Die Entscheidung, mit der Zählung zu beginnen 0, hat seitdem alle digitalen Systeme , einschließlich der darauf ausgeführten Software, durchdrungen , da der Code einfacher in das übersetzt werden kann, was das zugrunde liegende System interpretieren kann. Wenn dies nicht der Fall wäre, würde es für jeden Array-Zugriff eine unnötige Übersetzungsoperation zwischen der Maschine und dem Programmierer geben. Es erleichtert das Kompilieren.
Zitat aus der Zeitung:

a[b]wurde wie *(a+b)in frühen Compilern implementiert . Auch heute kann man noch schreiben 2[a]statta[2] . Wenn die Indizes nicht bei 0 beginnen a[b]würden, würden sie sich in verwandeln *(a+b-1). Dies hätte 2 zusätzliche CPUs der Zeit anstelle von 0 erforderlich gemacht, was die Hälfte der Geschwindigkeit bedeutet. Offensichtlich nicht wünschenswert.
Denn 0 ist die Entfernung vom Zeiger auf den Kopf des Arrays zum ersten Element des Arrays.
Erwägen:
int foo[5] = {1,2,3,4,5};
Um auf 0 zuzugreifen, tun wir:
foo[0]
Aber foo zerfällt in einen Zeiger, und der obige Zugriff hat eine analoge Zeigerarithmetik, um darauf zuzugreifen
*(foo + 0)
Heutzutage wird die Zeigerarithmetik nicht mehr so häufig verwendet. Vor langer Zeit war es jedoch eine bequeme Möglichkeit, eine Adresse zu nehmen und X "Ints" von diesem Startpunkt weg zu bewegen. Wenn Sie einfach dort bleiben möchten, wo Sie sind, fügen Sie einfach 0 hinzu!
Weil der 0-basierte Index ...
array[index]
... implementiert werden als ...
*(array + index)
Wenn der Index auf 1 basieren würde, müsste der Compiler Folgendes generieren: *(array + index - 1)und dieses "-1" würde die Leistung beeinträchtigen.
Weil es den Compiler und Linker einfacher machte (einfacher zu schreiben).
Referenz :
"... Das Referenzieren des Speichers durch eine Adresse und einen Offset wird auf praktisch allen Computerarchitekturen direkt in der Hardware dargestellt, sodass dieses Designdetail in C die Kompilierung erleichtert."
und
"... das vereinfacht die Implementierung ..."
Der Array-Index beginnt immer mit Null. Nehmen wir an, die Basisadresse ist 2000. Jetzt arr[i] = *(arr+i). if i= 0Dies bedeutet nun , dass *(2000+0) gleich der Basisadresse oder der Adresse des ersten Elements im Array ist. Dieser Index wird als Offset behandelt, sodass der Standardindex bei Null beginnt.
Aus dem gleichen Grund, wenn es Mittwoch ist und jemand Sie fragt, wie viele Tage bis Mittwoch Sie 0 statt 1 sagen, und wenn es Mittwoch ist und jemand Sie fragt, wie viele Tage bis Donnerstag Sie 1 statt 2 sagen.
Die eleganteste Erklärung, die ich für die nullbasierte Nummerierung gelesen habe, ist die Beobachtung, dass Werte nicht an den markierten Stellen in der Zahlenreihe, sondern in den Zwischenräumen zwischen ihnen gespeichert werden. Das erste Element wird zwischen null und eins gespeichert, das nächste zwischen eins und zwei usw. Das n-te Element wird zwischen N-1 und N gespeichert. Ein Bereich von Elementen kann unter Verwendung der Zahlen auf beiden Seiten beschrieben werden. Einzelne Artikel werden gemäß Konvention mit den Zahlen darunter beschrieben. Wenn man einen Bereich (X, Y) erhält, bedeutet das Identifizieren einzelner Zahlen unter Verwendung der folgenden Nummer, dass man das erste Element ohne Verwendung einer Arithmetik identifizieren kann (es ist Element X), aber man muss eine von Y subtrahieren, um das letzte Element (Y) zu identifizieren -1). Das Identifizieren von Elementen anhand der obigen Nummer würde es einfacher machen, das letzte Element in einem Bereich zu identifizieren (es wäre Element Y).
Obwohl es nicht schrecklich wäre, Elemente anhand der darüber liegenden Zahl zu identifizieren, funktioniert es im Allgemeinen besser, das erste Element im Bereich (X, Y) als das über X zu definieren, als es als das unter (X +) zu definieren 1).
Der technische Grund könnte sich aus der Tatsache ergeben, dass der Zeiger auf einen Speicherort eines Arrays der Inhalt des ersten Elements des Arrays ist. Wenn Sie den Zeiger mit einem Index von eins deklarieren, addieren Programme normalerweise den Wert eins zum Zeiger, um auf den Inhalt zuzugreifen, der natürlich nicht Ihren Wünschen entspricht.
Versuchen Sie, mit X-, Y-Koordinaten auf einer 1-basierten Matrix auf einen Pixelbildschirm zuzugreifen. Die Formel ist äußerst komplex. Warum ist komplex? Weil Sie am Ende die X- und Y-Koordinaten in eine Zahl umwandeln, den Offset. Warum müssen Sie X, Y in einen Offset konvertieren? Denn so ist der Speicher in Computern als kontinuierlicher Strom von Speicherzellen (Arrays) organisiert. Wie gehen Computer mit Array-Zellen um? Verwenden von Offsets (Verschiebungen aus der ersten Zelle, ein auf Null basierendes Indexierungsmodell).
Irgendwann im Code müssen Sie (oder der Compiler) die 1-Basis-Formel in eine 0-basierte Formel konvertieren, da Computer so mit Speicher umgehen.
Angenommen, wir möchten ein Array der Größe 5 erstellen.
Int array [5] = [2,3,5,9,8]
Lassen Sie das erste Element des Arrays auf Position 100 zeigen
und betrachten Sie, dass die Indizierung bei 1 beginnt und nicht bei 0.
Jetzt müssen wir die Position des 1. Elements mit Hilfe des Index ermitteln
(denken Sie daran, dass die Position des 1. Elements 100 ist),
da die Größe einer Ganzzahl 4 Bit beträgt.
> Wenn Sie Index 1 berücksichtigen, wäre die Position die
Größe von Index (1) * Größe der ganzen Zahl (4) = 4,
so dass die tatsächliche Position, die es uns zeigt,
100 + 4 = 104 ist
Dies ist nicht wahr, da die anfängliche Position bei 100 lag.
Es sollte auf 100 zeigen, nicht auf 104.
Dies ist falsch.
Nehmen wir nun an, wir haben die Indizierung von 0 genommen,
dann sollte die
Position des 1. Elements die
Größe des Index (0) * Größe der Ganzzahl sein (4) = 0
daher ->
Position des 1. Elements ist 100 + 0 = 100
und das war die tatsächliche Position des Elements
deshalb beginnt die Indizierung bei 0;
Ich hoffe, es wird Ihren Standpunkt klarstellen.
Ich komme aus Java. Ich habe die Antwort auf diese Frage in der folgenden Abbildung dargestellt, die ich in einem selbsterklärenden Blatt Papier geschrieben habe
Hauptschritte:
Hinweis : Die im Bild gezeigten Blöcke sind Speicherdarstellungen
Zunächst müssen Sie wissen, dass Arrays intern als Zeiger betrachtet werden, da der "Name des Arrays selbst die Adresse des ersten Elements des Arrays enthält".
ex. int arr[2] = {5,4};
Beachten Sie, dass das Array bei Adresse 100 beginnt, sodass das erste Element bei Adresse 100 und das zweite bei 104 liegt. Wenn der Array-Index bei 1 beginnt, ist dies der Fall
arr[1]:-
Dies kann in den Zeigerausdruck wie folgt geschrieben werden:
arr[1] = *(arr + 1 * (size of single element of array));
Angenommen, die Größe von int beträgt jetzt 4 Byte.
arr[1] = *(arr + 1 * (4) );
arr[1] = *(arr + 4);
Wie wir wissen, enthält der Array-Name die Adresse seines ersten Elements.
arr[1] = *(100 + 4);
arr[1] = *(104);
was gibt,
arr[1] = 4;
Aufgrund dieses Ausdrucks können wir nicht auf das Element unter der Adresse 100 zugreifen, die das offizielle erste Element ist.
Betrachten Sie nun, dass der Array-Index bei 0 beginnt
arr[0]:-
Dies wird als gelöst
arr[0] = *(arr + 0 + (size of type of array));
arr[0] = *(arr + 0 * 4);
arr[0] = *(arr + 0);
arr[0] = *(arr);
Jetzt wissen wir, dass der Array-Name die Adresse seines ersten Elements enthält.
arr[0] = *(100);
das gibt korrektes Ergebnis
arr[0] = 5;
Daher beginnt der Array-Index in c immer bei 0.
Referenz: Alle Details sind in Buch "Die C-Programmiersprache von Brian Kerninghan und Dennis Ritchie" geschrieben.
Im Array gibt der Index den Abstand zum Startelement an. Das erste Element befindet sich also in einem Abstand von 0 vom Startelement. Deshalb beginnt das Array bei 0.
Dies liegt daran address, dass das elementim Array nach rechts zeigen muss . Nehmen wir das folgende Array an:
let arr = [10, 20, 40, 60];
Wenden wir uns nun den Beginn der Adresse Wesen betrachten 12und die Größe des elementsei 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
Wenn dies nicht zero-based der arrayFall wäre, wäre technisch gesehen unsere erste Elementadresse in der , 16die aufgrund ihres Standorts falsch ist 12.
Der Array-Name ist ein konstanter Zeiger, der auf die Basisadresse zeigt. Wenn Sie arr [i] verwenden, manipuliert der Compiler ihn als * (arr + i). Da der int-Bereich -128 bis 127 beträgt, glaubt der Compiler, dass -128 bis -1 sind negative Zahlen und 0 bis 128 sind positive Zahlen. Der Array-Index beginnt also immer mit Null.
intTyp ist erforderlich, um mindestens einen 16-Bit-Bereich zu unterstützen, und auf den meisten Systemen werden heutzutage 32-Bit unterstützt. Ich denke, Ihre Logik ist fehlerhaft und Ihre Antwort verbessert sich nicht wirklich gegenüber den anderen Antworten, die bereits von anderen Personen gegeben wurden. Ich schlage vor, dies zu löschen.