Warum beginnen Arrays bei Index 0?
-
Hi
Welchen Grund hat es, dass Arrays bei Index 0 und nicht bei 1 beginnen? Ist das nur eine Definitionssache oder hat es andere Gründe z.B. wegen Hardware oder Optimierung oder ähnlichem?
Denn intuitiver wäre es zu sagen, das erste Element hat Index 1...
-
Praktisch: Das ist alles eine Frage der Definition (und Gewohnheit).
Technisch: Array-Arithmetik basiert auf Zeiger-Arithmetik. Und bei einem Zeiger ist p[i] == *(p+i) das Element, das i Felder hinter der Adresse p steht - und p[0] == *(p+0) == *p ist das Element, auf das p zeigt (also das Anfangselement des "Arrays" p). Warum sollte der Zugriff also bei einem echten Array anders sein (besonders wenn man bedenkt, daß echte Arrays bei jeder passenden Gelegenheit als Pointer betrachtet werden).
-
deine "technische" ausführung basiert strikt auf den annahmen deiner "praktischen" ausführung
"bei einem Zeiger ist p[i] == *(p+i) das Element, das i Felder hinter der Adresse p steht" liesse sich bei anderer definition auch als:
"p[i] === *(p+i) ist das Element, dass sich an Position i hinter der Adresse befindet", somit findet sich an 1 das erste element.dass arrays in den meisten sprachen (nicht allen!) bei 0 beginnen ist darin begründet, dass im amerikanischen sprachraum in der mathematik indizes bei 0 beginnen. das war schon lange vor der "erfindung" von programmiersprachen so und hat sich logischerweise dann auf diese übertragen. im deutschen sprachraum haben indizes ursprünglicherweise bei 1 begonnen. das hat sich in den letzten jahrzehnten allerdings mehr und mehr an die 0-tradition angepasst.
und das ist eigentlich alles. da steckt keine magie hinter
es spielt aus performance sicht und dergleichen absolut keine rolle. es ist schlicht definition bzw. gewohnheit.
-
keinlehrer schrieb:
es spielt aus performance sicht und dergleichen absolut keine rolle
Das dürfte unbestritten sein. Ein -1 bei sämtlichen Indizes wäre nicht das Problem für den Compilerhersteller, wenn das die Performance verbessert
-
Die Begründung hat nichts mit irgendwelchen angeblichen amerkanischen Indezierungsgewohneheiten zu tun sondern ist in der Tat rein technisch, wie CStoll schon sagte. Ein Array ist einfach ein zusammenhängender Speicherbereich fester Größe. Wie bei jeder Variabel hat man von diesem nur die Speicheradresse - und zwar den Anfang des Speicherbereichs. Die "Unterteilungen" in die verschiedene Elemente erhält man, wenn man sizeof(Datentyp der Elemente) auf die Startadresse addiert. Ein Indexstart bei 1 würde eben immer eine Subtraktion von 1 vom Index notwendig machen. Das könnte man natürlich machen. Aber die Programmiersprache C hat eben eine geringere Abstraktion und hat es deswegen bei 0 als Beginn belassen. Erst jetzt kommt die Gewohnheit mit ins Spiel: nämlich bei Sprachen höhrer Abstraktion.
-
Genau, die Ausführungen von keinlehrer sind vollkommener Schwachsinn, aber was will man bei dem Namen erwarten
-
minhen schrieb:
Ein Indexstart bei 1 würde eben immer eine Subtraktion von 1 vom Index notwendig machen.
Nicht um bedingt. Man könnte den Zeiger auch einfach auf das erste Element vor dem eigentlichen Array zeigen lassen.
-
Ben04 schrieb:
Man könnte den Zeiger auch einfach auf das erste Element vor dem eigentlichen Array zeigen lassen.
Das Verhalten ist dann leider nicht definiert.
-
Bashar schrieb:
Ben04 schrieb:
Man könnte den Zeiger auch einfach auf das erste Element vor dem eigentlichen Array zeigen lassen.
Das Verhalten ist dann leider nicht definiert.
Wieso nicht? Vom technischen Standpunkt her gibt es jedenfalls keine Probleme.
-
5.7§5 (Es geht um Pointer-Addition) "If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array, the evaluation shall not produce an overflow; otherwise, the behavior is undefined."
-
Wobei ich mir fast sicher bin dass der Teil "or one past the last element of the array" auch nur seinen Weg in den Standard gefunden hat um Iteratoren für std::vector einfach und schnell zu machen, und für Ähnliche Fälle wo man halb offene Intervalle mit Zeigern verwenden möchte.
EDIT: man könnte den Zeiger trotzdem einfach eins vor das erste Element zeigen lassen, denn in einer Sprache wo eben a[1] das erste Element bezeichnet wäre wohl der C++ Standard nicht anwendbar und daher auch kein Problem. "Technisch" im Sinne von "was kann auf den meisten Plattformen implementiert werden" ist es also sicher kein Problem. In Pascal z.B. kann ich mir überhaupt aussuchen wo ein Array losgeht, und Pascal Compiler gibts auch für genügend Plattformen.
-
hustbaer schrieb:
EDIT: man könnte den Zeiger trotzdem einfach eins vor das erste Element zeigen lassen, denn in einer Sprache wo eben a[1] das erste Element bezeichnet wäre wohl der C++ Standard nicht anwendbar und daher auch kein Problem. "Technisch" im Sinne von "was kann auf den meisten Plattformen implementiert werden" ist es also sicher kein Problem. In Pascal z.B. kann ich mir überhaupt aussuchen wo ein Array losgeht, und Pascal Compiler gibts auch für genügend Plattformen.
Stimmt, das bezieht sich dann eher darauf, in C++ Arrays, die bei 1 anfangen, effizient nachzubilden.
-
Amateur schrieb:
Hi
Welchen Grund hat es, dass Arrays bei Index 0 und nicht bei 1 beginnen? Ist das nur eine Definitionssache oder hat es andere Gründe z.B. wegen Hardware oder Optimierung oder ähnlichem?
Denn intuitiver wäre es zu sagen, das erste Element hat Index 1...Streng mathematisch betrachtet basiert unser Zahlensystem auf den Zahlen 0-9. Viele Menschen glauben aber fälschlicherweise unser Zahlensystem basiere auf 1-10, was aber schlicht falsch ist...
Die Array-Implementierung ist also mathematisch korrekt, es ist eher die menschliche Seite die zu ungenau ist...
-
skals schrieb:
Amateur schrieb:
Hi
Welchen Grund hat es, dass Arrays bei Index 0 und nicht bei 1 beginnen? Ist das nur eine Definitionssache oder hat es andere Gründe z.B. wegen Hardware oder Optimierung oder ähnlichem?
Denn intuitiver wäre es zu sagen, das erste Element hat Index 1...Streng mathematisch betrachtet basiert unser Zahlensystem auf den Zahlen 0-9. Viele Menschen glauben aber fälschlicherweise unser Zahlensystem basiere auf 1-10, was aber schlicht falsch ist...
Die Array-Implementierung ist also mathematisch korrekt, es ist eher die menschliche Seite die zu ungenau ist...
Unser Zahlensystem basiert auf der Zahl 10 (10 ist die sog. Basis), und schreiben tun wir es mit den Ziffern 0-9. Die Zahlen 0 bis 9 haben dabei keine besondere Bedeutung.
EDIT: was im übrigen nichts mit Arrays in C oder C++ zu tun hat. /EDIT
Was "mathematisch korrekt" ist ist im übrigen Definitionssache, und wenn ich eine Menge aus N Elementen definiere und diese mit E_1 bis E_10 bezeichne, dann ist das eben so. Wenn ich sie E_0 bis E_9 nenne ist es eben anders. Korrekt ist beides. Davon abgesehen dass C nichts mit Mathematik zu tun hat.
Zurück zur Frage "warum beginnen Arrays (in C und C++) mit Index 0?". C++ ist leicht zu beantworten, nämlich weil Arrays in C mit Index 0 beginnen. Und C ... ist auch nicht viel schwieriger, nämlich weil man es in Assembler auch üblicherweise so macht, also den Zeiger auf der erste Element zeigen lässt und nicht davor, und so muss der Index eben 0 sein. Zumindest bin ich davon überzeugt dass sich da niemand gross was dabei überlegt hat, sondern einfach das übernommen wurde was bei Assemblerprogrammierung gang und gebe war, und vor allem leicht in Assembler überzuführen ist.
-
In Assembler sieht man auch schön, dass Variabelnamen nur Offsets sind und letztlich für Speicheradressen stehen. Das gilt sowohl für "normale" Variabeln als auch für Arrays. Man hat im Grunde also nur Zeiger - und denen sieht man eben nicht an, ob etwas ein Array ist oder nicht. Daher ist aus technischer Sicht völlig klar, weshalb für Arrays das selbe gelten muss wie für Variabeln elementarer Typen: der Variabelnamen zeigt auf den Anfang des Speicherbereichs und nicht etwa auf ein Element davor.
Um das Problem zu veranschaulichen:void foo(int* bar) { // Ist bar ein Array von int oder nur ein Zeiger auf ein int? }
Die Behandlung von Arrays und elementaren Datentypen muss auf dieser Ebene also einheitlich sein. Und da es bei elementaren Typen ziemlich sinnlos ist vor den eigentlichen Speicherbereich zu zeigen, werden Arrays eben mit 0 beginnend indiziert.
Wie ich schon gesagt habe: dass Arrays in C bei 0 beginnen ist der geringen Abstraktion von C zu verdanken. Und dass es bei vielen Sprachen höherer Abstraktion auch so gemacht wird, ist wiederum der Gewohnheit anzulasten.
-
hustbaer schrieb:
EDIT: man könnte den Zeiger trotzdem einfach eins vor das erste Element zeigen lassen, denn in einer Sprache wo eben a[1] das erste Element bezeichnet wäre wohl der C++ Standard nicht anwendbar und daher auch kein Problem. "Technisch" im Sinne von "was kann auf den meisten Plattformen implementiert werden" ist es also sicher kein Problem. In Pascal z.B. kann ich mir überhaupt aussuchen wo ein Array losgeht, und Pascal Compiler gibts auch für genügend Plattformen.
In C, C++ geht es wohl eher um diesen "Trick":
int realarray[10]; int *array = &realarray[-1];
-
minhen schrieb:
Wie ich schon gesagt habe: dass Arrays in C bei 0 beginnen ist der geringen Abstraktion von C zu verdanken.
finde ich auch, in C ist es einfach der offset in den speicher. in höheren sprachen würde man eher ordinalzahlen (erstes, zeites, drittes, usw...) nehmen, weil in solchen sprachen maschinennahe betrachtungsweisen keine rolle spielen, auch keine adressen, pointer usw...
-
finix schrieb:
int realarray[10]; int *array = &realarray[-1];
böser trick, das gibt afaik undefiniertes verhalten!?
-
0 ist keine Zahl. Weil es sich nicht multiplizieren und addieren lässt. typisch amerikanisch.
das ist ein menschlicher denkfehler.für mich ist das 1-10. damit division durch 0 ausgeschlossen ist.
kann man C++ so manipulieren dass die Zahl 0 nicht mehr existiert? Der anfang nur 1 und die negativen zahlen -1 ohne die 0 als zwischenraum?
-
dot schrieb:
böser trick, das gibt afaik undefiniertes verhalten!?
Ja, siehe die vorigen Beiträge.
-
...