127 votes

Pourquoi sizeof (my_arr) [0] est-il compilé et égal à sizeof (my_arr [0])?

Pourquoi est-ce que le code de la compilation?

_Static uint32_t my_arr[2];
_Static_assert(sizeof(my_arr) == 8, "");
_Static_assert(sizeof(my_arr[0]) == 4, "");
_Static_assert(sizeof(my_arr)[0] == 4, "");

Les 2 premières assertions sont évidemment correct, mais je me serais attendu à la dernière ligne à l'échec, car ma compréhension est qu' sizeof() doit correspondre à un entier littéral, qui ne peut pas être traitée comme un tableau. En d'autres termes, il ne pourrait pas de la même manière que la ligne suivante échoue:

_Static_assert(4[0] == 4, "");

Fait intéressant, la suite n'est en effet l'échec de la compilation (ce qui devrait faire la même chose, non?):

_Static_assert(*sizeof(my_arr) == 4, "");

erreur: invalid argument de type de unaire ' * ' (, 'de long unsigned int") _Static_assert(*sizeof(my_arr) == 4, "");

Si il le faut, je suis en utilisant gcc 5.3.0

192voto

melpomene Points 5675

sizeof n'est pas une fonction. C'est un opérateur unaire comme ! ou ~.

sizeof(my_arr)[0] s'analyse comme sizeof (my_arr)[0], ce qui est juste sizeof my_arr[0] redondantes entre parenthèses.

C'est juste comme !(my_arr)[0] s'analyse comme !(my_arr[0]).

En général, postfix opérateurs ont une priorité plus élevée que les opérateurs de préfixe dans C. sizeof *a[i]++ s'analyse comme sizeof (*((a[i])++)) (les opérateurs de suffixe [] et ++ sont appliqués à l' a d'abord, puis les opérateurs de préfixe * et sizeof).

(C'est l'expression de la version de sizeof. Il y a également un type de version, qui prend une mise entre parenthèses de type nom: sizeof (TYPE). Dans ce cas, les parens serait nécessaire, et une partie de l' sizeof de la syntaxe.)

45voto

AndreyT Points 139512

sizeof a deux "versions": sizeof(type name) et sizeof expression. La première nécessite une paire de () autour de son argument. Mais ce dernier - l'un avec comme argument une expression - n'ont pas d' () autour de son argument. Quelle que soit () vous utiliser dans l'argument est considéré comme faisant partie de l'argument de l'expression, ne fait pas partie de l' sizeof de la syntaxe elle-même.

Depuis my_arr est connu pour le compilateur comme un nom d'objet, pas un nom de type, votre sizeof(my_arr)[0] est réellement vu par le compilateur comme sizeof appliquée à une expression: sizeof (my_arr)[0](my_arr)[0] est l'expression d'argument. L' () entourant le nom du tableau est purement superflu. Cette expression est interprétée comme sizeof my_arr[0]. C'est l'équivalent de votre précédente sizeof(my_arr[0]).

(Ce qui signifie, d'ailleurs, que votre précédente sizeof(my_arr[0]) contient également une paire de superflu ().)

C'est plutôt une idée fausse très répandue que sizeofs'la syntaxe d'une certaine manière nécessite une paire de () autour de son argument. Cette idée fausse est ce qui trompe les gens de l'intuition lors de l'interprétation des expressions telles que sizeof(my_arr)[0].

24voto

mch Points 4825

[] ont une préséance supérieure à sizeof . Ainsi, sizeof(my_arr)[0] est identique à sizeof((my_arr)[0]) .

Voici un lien vers un tableau de priorité.

7voto

Quentin Points 3904

Vous utilisez la version de l'opérateur sizeof qui prend une expression en paramètre. Contrairement à celui qui prend un type, il ne nécessite pas de parenthèses. Par conséquent, l'opérande est simplement (my_arr)[0] , les parenthèses étant redondantes.

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