1814 votes

Avec C des tableaux, pourquoi est-ce le cas que a[5] == 5[a] ?

Comme Joel points dans le Débordement de la Pile podcast #34, dans le Langage de Programmation C (aka: K & R), il est fait mention de cette propriété de tableaux en C: a[5] == 5[a]

Joel dit que c'est à cause de l'arithmétique des pointeurs, mais je ne comprends toujours pas. Pourquoi est - a[5] == 5[a] ?

2139voto

Mehrdad Afshari Points 204872

La norme définit l' [] opérateur comme suit:

a[b] == *(a + b)

Par conséquent, a[5] donnera:

*(a + 5)

et 5[a] donnera:

*(5 + a)

et de l'école élémentaire de mathématiques nous savons que ceux-ci sont égaux.

C'est la directe conséquence de tableaux à se comporter comme des pointeurs, "a" est une adresse mémoire. "a[5]" est la valeur 5 éléments supplémentaires à partir de "a". L'adresse de cet élément est "a + 5". C'est l'équivalent d'offset "a "" 5" éléments au début de l'espace d'adressage (5 + a).

307voto

David Thornley Points 39051

Parce que l'accès au tableau est définie en termes de pointeurs. a[i] définition *(a + i), ce qui est commutatif.

291voto

Keith Thompson Points 85120

De façon réaliste, je ne vais pas en concurrence avec la accepté de répondre (ce qui, comme je l'ai écris ceci, a 720 722 net upvotes), mais je pense que quelque chose est en train de manquer.

Oui, p[i] est par définition égale à *(p+i), (parce que l'addition est commutative) est équivalent à *(i+p), ce qui (encore une fois, par la définition de l' [] opérateur) est équivalent à i[p].

(Et en array[i], le nom du tableau est implicitement converti en un pointeur vers le premier élément du tableau.)

Mais la commutativité de l'addition n'est pas du tout évident dans ce cas.

Lorsque les deux opérandes sont de même type, ou même de différents types numériques qui sont promus à un type commun, la commutativité est parfaitement logique: x + y == y + x.

Mais dans ce cas, nous parlons spécifiquement sur l'arithmétique des pointeurs, où l'un des opérandes est un pointeur et l'autre est un entier. (Nombre entier + entier est une autre opération, et + de pointeur de pointeur est un non-sens.)

Le C standard description de l' + opérateur (N1570 6.5.6) dit:

De plus, les deux opérandes ont arithmétique de type, ou un l'opérande doit être un pointeur vers un objet de type et les autres aura de type entier.

Il aurait tout aussi bien pu dire:

De plus, les deux opérandes ont arithmétique de type, ou de la gauche l'opérande doit être un pointeur vers un objet de type et l' opérande de droite aura de type entier.

dans ce cas, i + p et i[p] serait illégal.

En C++ termes, nous avons en fait deux ensembles de surchargés + opérateurs, ce qui peut être vaguement décrit comme:

pointer operator+(pointer p, integer i);

et

pointer operator+(integer i, pointer p);

dont seul le premier est vraiment nécessaire.

Alors pourquoi est-il de cette façon?

C++ hérité de cette définition de C, qui a obtenu à partir de B (la commutativité de tableau d'indexation est explicitement mentionné dans l'1972 Utilisateurs Référence B), qui a obtenu de BCPL (manuel daté de 1967), a peut-être obtenu à partir encore plus tôt langues (CPL? Algol?).

Donc, l'idée que le tableau d'indexation est définie en termes de plus, et que de plus, même d'un pointeur et un entier, est commutative, remonte à plusieurs décennies, à C de l'ancêtre de langues.

Ces langues étaient beaucoup moins fortement typé moderne que C est. En particulier, la distinction entre les pointeurs et les entiers a souvent été ignorée. (Début de programmeurs C parfois utilisé des pointeurs comme des entiers non signés, avant la unsigned mot-clé a été ajoutée à la langue.) Donc l'idée de faire plus de non-commutative parce que les opérandes sont de types différents n'auraient probablement pas eu lieu pour les concepteurs de ces langues. Si un utilisateur veut ajouter deux "choses", que ces "choses" sont des nombres entiers, des pointeurs, ou quelque chose d'autre, il n'était pas jusqu'à la langue pour l'empêcher.

Et au fil des années, toute modification apportée à cette règle aurait brisé le code existant (bien que l'1989 C ANSI standard aurait pu être une bonne occasion).

Changement de C et/ou C++ pour exiger de mettre le pointeur sur la gauche et l'entier sur la droite pourraient casser le code existant, mais il n'y aurait aucune perte réelle de la puissance expressive.

Alors maintenant, nous avons arr[3] et 3[arr] sens exactement la même chose, bien que cette dernière forme ne doit jamais apparaître à l'extérieur de l' IOCCC.

210voto

James Curran Points 55356

Et, bien sûr,

 "ABCD"[2] == 2["ABCD"] == 'C'

La principale raison pour cela est que dans les années 70 quand le C a été conçu, les ordinateurs n'ont pas beaucoup de mémoire (64 KO en a beaucoup), de sorte que le compilateur C n'a pas fait beaucoup vérification de la syntaxe. De là "X[Y]" a été plutôt se traduire par "*(X+Y)"

Ce qui explique aussi le "+=" et "++" syntaxes. Tout dans la forme "A = B + C" avaient la même forme compilée. Mais, si B est le même objet que d'Une, puis une assemblée niveau d'optimisation ont été disponibles. Mais le compilateur n'a pas assez lumineux pour la reconnaître, de sorte que le développeur a (A += C). De même, si C a 1, un autre au niveau de l'assemblée optimisation a été disponible, et encore, le développeur a le rendre explicite, parce que le compilateur ne pas le reconnaître. (Plus récemment, les compilateurs n', de sorte que ces syntaxes sont en grande partie inutiles de ces jours)

59voto

user30364 Points 364

Une chose que personne ne semble avoir mentionné sur Dinah problème avec sizeof:

Vous ne pouvez ajouter un entier à un pointeur, vous ne pouvez pas ajouter deux pointeurs ensemble. De cette façon, lors de l'ajout d'un pointeur vers un entier, ou d'un entier à un pointeur, le compilateur sait toujours qui peu a une taille qui doit être pris en compte.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X