Pourquoi ce code se compile-t-il?
_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 correctes, mais je me serais attendu à ce que la dernière ligne échoue, car je crois comprendre que cela sizeof()
devrait être évalué à un littéral entier, qui ne peut pas être traité comme un tableau. En d'autres termes, il échouerait de la même manière que la ligne suivante échoue:
_Static_assert(4[0] == 4, "");
Fait intéressant, ce qui suit échoue en effet à compiler (ce qui devrait faire la même chose, non?):
_Static_assert(*sizeof(my_arr) == 4, "");
erreur: argument de type non valide d'unaire '*' (avoir 'long unsigned int') _Static_assert (* sizeof (my_arr) == 4, "");
Si cela compte, j'utilise gcc 5.3.0
( sizeof( my_arr ) )[ 0 ]
échec.Réponses:
sizeof
n'est pas une fonction. C'est un opérateur unaire comme!
ou~
.sizeof(my_arr)[0]
analyse commesizeof (my_arr)[0]
, qui est justesizeof my_arr[0]
avec des parenthèses redondantes.C'est exactement comme l'
!(my_arr)[0]
analyse!(my_arr[0])
.En général, les opérateurs de suffixe ont une priorité plus élevée que les opérateurs de préfixe dans C.
sizeof *a[i]++
analyse commesizeof (*((a[i])++))
(les opérateurs de suffixe[]
et++
sont appliqués ena
premier, puis les opérateurs de préfixe*
etsizeof
).(Il s'agit de la version d'expression de
sizeof
. Il existe également une version de type, qui prend un nom de type entre parenthèses:.sizeof (TYPE)
Dans ce cas, les parenthèses seraient obligatoires et feraient partie de lasizeof
syntaxe.)la source
sizeof
être un opérateur unaire."... parses as sizeof (my_arr[0])"
? L'ajout d'un espace ne change vraiment rien.sizeof((my_array)[0])
plutôtsizeof
a deux "versions":sizeof(type name)
etsizeof expression
. Le premier nécessite une paire de()
autour de son argument. Mais ce dernier - celui avec une expression comme argument - n'a pas()
autour de son argument. Tout()
ce que vous utilisez dans l'argument est considéré comme faisant partie de l'expression d'argument et non comme faisant partie de lasizeof
syntaxe elle-même.Étant donné que
my_arr
le compilateur est connu comme un nom d'objet et non comme un nom de type, votresizeof(my_arr)[0]
est en fait vu par le compilateur commesizeof
appliqué à une expression:,sizeof (my_arr)[0]
où(my_arr)[0]
est l'expression d'argument. Le()
nom du tableau qui entoure est purement superflu. L'expression entière est interprétée commesizeof my_arr[0]
. Ceci est équivalent à votre précédentsizeof(my_arr[0])
.(Cela signifie, BTW, que votre précédent
sizeof(my_arr[0])
contient également une paire de superflus()
.)C'est une idée fausse assez répandue selon laquelle
sizeof
la syntaxe de la syntaxe nécessite en quelque sorte une paire de()
autour de son argument. Cette idée fausse est ce qui trompe l'intuition des gens lors de l'interprétation de telles expressions commesizeof(my_arr)[0]
.la source
int
n'est pas une expression valide, vous ne pouvez donc pas utiliser le deuxième forme avec elle.[]
ont une priorité plus élevée quesizeof
. C'est doncsizeof(my_arr)[0]
la même chose quesizeof((my_arr)[0])
.Voici un lien vers une table de priorité.
la source
Vous utilisez la version de l'
sizeof
opérateur qui prend une expression comme 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.la source