Pourquoi l’indexation dans un tableau commence-t-elle par zéro en C et non par 1?
En C, le nom d'un tableau est essentiellement un pointeur, une référence à un emplacement de mémoire. Le tableau d'expressions [n] fait donc référence à un emplacement de mémoire n-éléments à l'écart de l'élément de départ. Cela signifie que l'index est utilisé comme un décalage. Le premier élément du tableau est exactement contenu dans l'emplacement mémoire référencé par le tableau (0 élément éloigné), il doit donc être noté tableau [0].
pour plus d'informations:
http://developeronline.blogspot.com/2008/04/why-array-index-should-start-from-0.html
Cette question a été postée il y a plus d'un an, mais voici ...
Bien que article de Dijkstra (précédemment référencé dans un réponse maintenant supprimé) ait un sens d'un point de vue mathématique, il n'est pas aussi pertinent en matière de programmation.
La décision prise par les concepteurs de spécifications de langage et de compilateur est basée sur la décision prise par les concepteurs de systèmes informatiques de commencer à compter à 0.
Citant un plaidoyer pour la paix de Danny Cohen.
Pour toute base b, les premiers b ^ N entiers non négatifs sont représentés par exactement [~ # ~] n [~ # ~] chiffres (y compris les zéros non significatifs) uniquement si la numérotation commence à 0.
Cela peut être testé assez facilement. En base 2, prenez 2^3 = 8
Le 8ème numéro est:
111
peut être représenté avec 3
bits, tandis que 1000
nécessitera un bit supplémentaire (4 bits).
Les adresses mémoire de l'ordinateur ont 2^N
cellules adressées par N
bits. Maintenant, si nous commençons à compter à 1, 2^N
les cellules auraient besoin de N+1
lignes d'adresse. L'extra-bit est nécessaire pour accéder à exactement 1 adresse. (1000
dans le cas ci-dessus.). Une autre façon de le résoudre serait de laisser la dernière adresse inaccessible et d'utiliser N
lignes d'adresse.
Les deux sont solutions sous-optimales, par rapport au nombre de départ à 0, qui garderait toutes les adresses accessibles, en utilisant exactement N
lignes d'adresse!
La décision de commencer compte à 0
, depuis, a imprégné tous les systèmes numériques , y compris le logiciel qui les exécute, car il est plus simple de traduire le code en quoi correspond le système sous-jacent. peut interpréter. Si ce n'était pas le cas, il y aurait une opération de traduction inutile entre la machine et le programmeur, pour chaque accès au tableau. Cela facilite la compilation.
Citation de l'article:
Parce que 0 est la distance qui sépare le pointeur de la tête du tableau du premier élément du tableau.
Considérer:
int foo[5] = {1,2,3,4,5};
Pour accéder à 0 on fait:
foo[0]
Mais foo se décompose en un pointeur, et l'accès ci-dessus a un moyen arithmétique analogue de pointeur d'y accéder
*(foo + 0)
De nos jours, l'arithmétique des pointeurs n'est pas utilisée aussi fréquemment. À l'époque, c'était un moyen commode de prendre une adresse et de déplacer X "ints" de ce point de départ. Bien sûr, si vous vouliez rester où vous êtes, ajoutez 0!
Parce que l'indice basé sur 0 permet ...
array[index]
... à mettre en œuvre comme ...
*(array + index)
Si index était basé sur 1, le compilateur aurait besoin de générer: *(array + index - 1)
, et ce "-1" nuirait à la performance.
Parce que cela rend le compilateur et l'éditeur de liens plus simple (plus facile à écrire).
"... Le référencement de la mémoire à l'aide d'une adresse et d'un offset est représenté directement dans le matériel de pratiquement toutes les architectures informatiques, ce qui explique la conception détaillée en C facilitant la compilation"
et
"... cela simplifie la mise en oeuvre ..."
L'indice de tableau commence toujours par zéro. Supposons que l'adresse de base soit 2000. Maintenant, arr[i] = *(arr+i)
. Maintenant if i= 0
, ça signifie *(2000+0
) est égal à l'adresse de base ou à l'adresse du premier élément du tableau. cet index est traité comme un offset, donc l'index bydeafault commence à zéro.
Pour la même raison que, quand on est mercredi et que quelqu'un vous demande combien de jours jusqu'à mercredi, vous dites 0 plutôt que 1, et que lorsqu'il est mercredi et que quelqu'un vous demande combien de jours avant jeudi, vous dites 1 plutôt que 2.
L'explication la plus élégante que j'ai lue pour la numérotation à base zéro est une observation selon laquelle les valeurs ne sont pas stockées aux emplacements marqués sur la droite numérique, mais plutôt dans les espaces qui les séparent. Le premier élément est stocké entre zéro et un, le suivant entre un et deux, etc. Le nième élément est stocké entre N-1 et N. Une plage d'éléments peut être décrite à l'aide des numéros situés de chaque côté. Les articles individuels sont décrits par convention en utilisant les numéros ci-dessous. Si l’on attribue une plage (X, Y), l’identification de nombres individuels à l’aide du numéro ci-dessous signifie que l’on peut identifier le premier élément sans utiliser d’arithmétique (c’est l’item X) mais il faut soustraire un de Y pour identifier le dernier élément (Y -1). Identifier les éléments en utilisant le numéro ci-dessus faciliterait l'identification du dernier élément d'une plage (il s'agirait de l'élément Y), mais plus difficile d'identifier le premier (X + 1).
Bien qu’il ne soit pas horrible d’identifier des éléments sur la base du nombre au-dessus d’eux, définir le premier élément de la plage (X, Y) comme étant celui au-dessus de X est généralement plus efficace que de le définir comme étant celui au-dessous (X + 1).
Je viens d'un Java arrière-plan. J'ai présenté la réponse à cette question dans le diagramme ci-dessous que j'ai écrit dans un bout de papier est explicite
Étapes principales:
Remarque : Les blocs affichés dans l'image sont des représentations en mémoire.
Supposons que nous voulions créer un tableau de taille 5
int array [5] = [2,3,5,9,8]
que le premier élément du tableau soit dirigé vers l’emplacement 100
et prenons l’indexation à partir de 1 et non de 0.
Nous devons maintenant trouver l'emplacement du premier élément à l'aide de l'index
(rappelez-vous que l'emplacement du 1er élément est 100)
puisque la taille d'un entier est 4 bits
donc -> compte tenu de l'indice 1, la position serait
taille de l'index (1) * taille de l'entier (4) = 4
donc la position réelle qu'il nous montrera est
100 + 4 = 104
ce qui n'est pas vrai car l'emplacement initial était à 100.
il devrait indiquer 100 et non pas 104
c'est faux
supposons maintenant que nous avons pris l'indexation de 0
ensuite
la position du 1er élément devrait être
taille de l'index (0) * taille de l'entier (4) = 0
donc ->
l'emplacement du 1er élément est 100 + 0 = 100
et c'était l'emplacement réel de l'élément
c'est pourquoi l'indexation commence à 0;
J'espère que cela clarifiera votre argument.
Essayez d’accéder à un écran de pixels en utilisant les coordonnées X, Y sur une matrice à 1. La formule est extrêmement complexe. Pourquoi est complexe? Parce que vous finissez par convertir les coordonnées X, Y en un seul nombre, le décalage. Pourquoi avez-vous besoin de convertir X, Y en offset? Parce que c'est ainsi que la mémoire est organisée à l'intérieur des ordinateurs, sous la forme d'un flux continu de cellules mémoire (matrices). Comment les ordinateurs traitent-ils les cellules d'un tableau? Utilisation de décalages (déplacements à partir de la première cellule, modèle d’indexation basé sur zéro).
Donc, à un moment donné du code, vous avez besoin (ou du compilateur) de convertir la formule 1 base en une formule 0, car c'est ainsi que les ordinateurs gèrent la mémoire.
La raison technique pourrait provenir du fait que le pointeur sur un emplacement mémoire d'un tableau correspond au contenu du premier élément du tableau. Si vous déclarez le pointeur avec un index égal à un, les programmes ajouteraient normalement cette valeur de un au pointeur pour accéder au contenu qui n’est pas ce que vous voulez, bien sûr.
tout d'abord, vous devez savoir que les tableaux sont considérés en interne comme des pointeurs, car le "nom du tableau lui-même contient l'adresse du premier élément du tableau".
ex. int arr[2] = {5,4};
considérez que le tableau commence à l’adresse 100, donc le premier élément sera à l’adresse 100 et le deuxième à 104, considérez que si l’indice du tableau commence à 1,
arr[1]:-
cela peut être écrit dans l'expression de pointeurs comme ceci-
arr[1] = *(arr + 1 * (size of single element of array));
considérer la taille de int est 4bytes, maintenant,
arr[1] = *(arr + 1 * (4) );
arr[1] = *(arr + 4);
comme nous le savons, le nom du tableau contient l'adresse de son premier élément, alors arr = 100 maintenant,
arr[1] = *(100 + 4);
arr[1] = *(104);
qui donne,
arr[1] = 4;
en raison de cette expression, nous ne pouvons pas accéder à l'élément à l'adresse 100 qui est le premier élément officiel,
maintenant considérer index de tableau commence à 0, donc
arr[0]:-
cela sera résolu comme
arr[0] = *(arr + 0 + (size of type of array));
arr[0] = *(arr + 0 * 4);
arr[0] = *(arr + 0);
arr[0] = *(arr);
maintenant, nous savons que le nom du tableau contient l'adresse de son premier élément,
arr[0] = *(100);
ce qui donne un résultat correct
arr[0] = 5;
par conséquent, l'index de tableau commence toujours à 0 dans c.
référence: tous les détails sont écrits dans le livre "Le langage de programmation C de brian kerninghan et dennis ritchie"