Pourquoi l'indexation dans un tableau commence-t-elle par zéro en C et non par 1?
Pourquoi l'indexation dans un tableau commence-t-elle par zéro en C et non par 1?
Réponses:
En C, le nom d'un tableau est essentiellement un pointeur [mais voyez les commentaires] , une référence à un emplacement mémoire, et donc l'expression se array[n]
réfère à un emplacement mémoire des n
éléments éloignés de l'élément de départ. Cela signifie que l'index est utilisé comme décalage. Le premier élément du tableau est exactement contenu dans l'emplacement mémoire auquel le tableau fait référence (à 0 élément), il doit donc être notéarray[0]
.
Pour plus d'informations:
http://developeronline.blogspot.com/2008/04/why-array-index-should-start-from-0.html
sizeof arr
donne la taille de l'objet tableau, pas la taille d'un pointeur.
sizeof
opérateur, ou l' &
opérateur unaire , ou est une chaîne littérale utilisée pour initialiser un tableau, une expression qui est de type" tableau de type "est converti en une expression de type" pointeur sur type "qui pointe vers l'élément initial de l'objet tableau et n'est pas une valeur l. Si l'objet tableau a une classe de stockage de registre, le comportement n'est pas défini. "
Cette question a été postée il y a plus d'un an, mais voilà ...
Bien que l'article de Dijkstra (précédemment référencé dans une réponse maintenant supprimée ) ait du sens d'un point de vue mathématique, il n'est pas aussi pertinent en matière de programmation.
La décision prise par la spécification du langage et les concepteurs de compilateurs est basée sur la décision prise par les concepteurs de systèmes informatiques de commencer à compter à 0.
Citation d' un plaidoyer pour la paix par 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 nombre est:
111
peut être représenté en utilisant des 3
bits, alors qu'il 1000
faudra un bit supplémentaire (4 bits).
Les adresses mémoire de l'ordinateur ont des 2^N
cellules adressées par N
bits. Maintenant, si nous commençons à compter à 1, les 2^N
cellules auraient besoin de N+1
lignes d'adresse. Le bit supplémentaire est nécessaire pour accéder à exactement 1 adresse. ( 1000
dans le cas ci-dessus.). Une autre façon de résoudre ce problème serait de laisser la dernière adresse inaccessible et d'utiliserN
des lignes d'adresse.
Les deux sont des solutions sous-optimales , par rapport au décompte de départ à 0, qui garderait toutes les adresses accessibles, en utilisant exactement N
les lignes d'adresse!
La décision de commencer à compter à 0
, a depuis imprégné tous les systèmes numériques , y compris les logiciels qui les exécutent, car elle simplifie la traduction du code en ce que 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.
Citant le papier:
a[b]
été implémenté comme *(a+b)
dans les premiers compilateurs. Même aujourd'hui, vous pouvez toujours écrire à la 2[a]
place de a[2]
. Maintenant, si les index ne commençaient pas à 0, ils a[b]
deviendraient *(a+b-1)
. Cela aurait nécessité 2 ajouts sur les processeurs de l'époque au lieu de 0, soit la moitié de la vitesse. Clairement pas souhaitable.
Parce que 0 est la distance entre le pointeur de la tête du tableau et le premier élément du tableau.
Considérer:
int foo[5] = {1,2,3,4,5};
Pour accéder à 0, nous faisons:
foo[0]
Mais foo se décompose en un pointeur, et l'accès ci-dessus a une manière arithmétique de pointeur analogue d'y accéder
*(foo + 0)
De nos jours, l'arithmétique des pointeurs n'est pas utilisée aussi fréquemment. Il y a bien longtemps, c'était un moyen pratique de prendre une adresse et d'éloigner X "ints" de ce point de départ. Bien sûr, si vous vouliez rester là où vous êtes, il vous suffit d'ajouter 0!
Parce que l'index basé sur 0 permet ...
array[index]
... à mettre en œuvre comme ...
*(array + index)
Si l'index était basé sur 1, le compilateur aurait besoin de générer:, *(array + index - 1)
et ce "-1" nuirait aux performances.
Parce que cela a simplifié le compilateur et l'éditeur de liens (plus facile à écrire).
"... Le référencement de la mémoire par une adresse et un décalage est représenté directement dans le matériel sur pratiquement toutes les architectures informatiques, donc ce détail de conception en C facilite la compilation"
et
"... cela simplifie la mise en œuvre ..."
L'index de tableau commence toujours par zéro. Supposons que l'adresse de base est 2000. Maintenant arr[i] = *(arr+i)
. Maintenant if i= 0
, cela 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 c'est mercredi et que quelqu'un vous demande combien de jours jusqu'à mercredi, vous dites 0 au lieu de 1, et que quand c'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 endroits marqués sur la droite numérique, mais plutôt dans les espaces entre elles. 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 en utilisant les nombres de chaque côté. Les éléments individuels sont par convention décrits en utilisant les numéros ci-dessous. Si l'on donne une plage (X, Y), l'identification des numéros individuels à l'aide du nombre ci-dessous signifie que l'on peut identifier le premier élément sans utiliser d'arithmétique (c'est l'élément X) mais il faut en soustraire un à Y pour identifier le dernier élément (Y -1). Identifier les éléments à l'aide du numéro ci-dessus faciliterait l'identification du dernier élément d'une plage (ce serait l'élément Y),
Bien qu'il ne soit pas horrible d'identifier les éléments en fonction du nombre au-dessus d'eux, définir le premier élément de la plage (X, Y) comme étant celui au-dessus de X fonctionne généralement mieux que de le définir comme celui ci-dessous (X + 1).
La raison technique peut provenir du fait que le pointeur vers un emplacement mémoire d'un tableau est le contenu du premier élément du tableau. Si vous déclarez le pointeur avec un index de 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.
Essayez d'accéder à un écran de pixels en utilisant les coordonnées X, Y sur une matrice basée sur 1. La formule est tout à fait 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, en tant que flux continu de cellules mémoire (tableaux). Comment les ordinateurs traitent les cellules de matrice? Utilisation de décalages (déplacements à partir de la première cellule, modèle d'indexation à base zéro).
Donc, à un moment donné du code, vous avez besoin (ou le compilateur a besoin) de convertir la formule de base 1 en une formule de base 0 parce que c'est ainsi que les ordinateurs traitent la mémoire.
Supposons que nous voulions créer un tableau de taille 5
int array [5] = [2,3,5,9,8]
que le 1er élément du tableau soit pointé à l'emplacement 100
et considérons que l'indexation commence à 1 et non à 0.
maintenant nous devons trouver l'emplacement du 1er é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 de 4 bits
donc -> en considérant l'index 1, la position serait la
taille of index (1) * size of integer (4) = 4
donc la position réelle qu'il nous montrera est
100 + 4 = 104
ce qui n'est pas vrai parce que l'emplacement initial était à 100.
il devrait pointer vers 100 et non vers 104
c'est faux
maintenant supposons que nous ayons pris l'indexation à partir de 0
alors la
position du 1er élément devrait être la
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 point de vue.
Je viens d'un fond Java. J'ai présenté la réponse à cette question dans le diagramme ci-dessous que j'ai écrit sur une feuille de papier qui s'explique d'elle-même
Principales étapes:
Remarque : les blocs affichés dans l'image sont une représentation en mémoire
tout d'abord il faut 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 second sera à 104 maintenant, considérez que si l'index du tableau commence à 1, donc
arr[1]:-
cela peut être écrit dans l'expression des pointeurs comme ceci-
arr[1] = *(arr + 1 * (size of single element of array));
considérez que la taille de int est de 4 octets, 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 donc arr = 100 maintenant,
arr[1] = *(100 + 4);
arr[1] = *(104);
qui donne,
arr[1] = 4;
à cause de cette expression, nous ne pouvons pas accéder à l'élément à l'adresse 100 qui est le premier élément officiel,
considérez maintenant que l'index du 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 donc,
arr[0] = *(100);
qui donne un résultat correct
arr[0] = 5;
par conséquent, l'index du tableau commence toujours à 0 en c.
référence: tous les détails sont écrits dans le livre "Le langage de programmation C par brian kerninghan et dennis ritchie"
Dans un tableau, l'index indique la distance par rapport à l'élément de départ. Ainsi, le premier élément est à 0 distance de l'élément de départ. C'est pourquoi le tableau commence à 0.
C'est parce que le address
doit pointer vers la droite element
dans le tableau. Supposons le tableau ci-dessous:
let arr = [10, 20, 40, 60];
Considérons maintenant le début de l'adresse étant 12
et la taille de l' element
être 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
Si ce n'était pas le cas zero-based
, techniquement, notre premier élément d'adresse dans le array
serait ce 16
qui est faux car son emplacement est 12
.
Le nom du tableau est un pointeur constant pointant vers l'adresse de base. Lorsque vous utilisez arr [i], le compilateur le manipule comme * (arr + i). Puisque la plage int est de -128 à 127, le compilateur pense que -128 à -1 sont les nombres négatifs et 0 à 128 sont des nombres positifs, donc l'index de tableau commence toujours par zéro.
int
type est requis pour prendre en charge au moins une plage de 16 bits, et sur la plupart des systèmes de nos jours prend en charge 32 bits. Je pense que votre logique est erronée et que votre réponse ne s'améliore pas vraiment par rapport aux autres réponses déjà fournies par d'autres personnes. Je suggère de supprimer ceci.