Les parenthèses font-elles une différence lors de la détermination de la taille d’un tableau?

Le programme suivant imprime le même numéro deux fois sur gcc 4.8.2:

#include  int main() { char a[13]; printf("sizeof a is %zu\n", sizeof a ); printf("sizeof(a) is %zu\n", sizeof(a)); } 

Selon cet article de reddit , gcc n’est pas conforme à la norme, car une expression entre parenthèses ne figure pas dans la liste des exceptions pour les cas où la décroissance de point à pointeur ne se produit pas.

Est-ce que ce gars est correct? Voici la citation standard pertinente:

Sauf s’il s’agit de l’opérande de l’opérateur sizeof ou de l’opérateur unary & , ou d’un littéral de chaîne de caractères utilisé pour initialiser un tableau de type caractère, ou d’un littéral de chaîne large utilisé pour initialiser un tableau avec un type d’élément compatible avec wchar_t , lvalue de type ‘tableau de type’ est convertie en une expression de type ‘pointeur sur type’ qui pointe vers le membre initial de l’object tableau et n’est pas une lvalue.

Pour clarifier les choses, il soutient que (a) devrait déclencher une décroissance de tableau à pointeur, car les parenthèses ne sont pas couvertes dans la liste ci-dessus (opérateur sizeof , unary & operator, chaîne littérale en tant qu’initialiseur).

Si des parenthèses apparemment redondantes affectent la sémantique d’un programme est un problème de longue date dans la norme C qui n’a toujours pas été résolu de manière adéquate.

Il est communément affirmé que ((void*)0) n’est techniquement pas une constante de pointeur nulle, car il n’y a pas de règle qui dit qu’une constante de pointeur nul entre parenthèses est une constante de pointeur nulle.

Certains compilateurs émettent une erreur pour char s[] = ("abc"); , car bien qu’un tableau de caractères puisse être initialisé à partir d’un littéral de chaîne, cette règle ne couvre pas les littéraux de chaîne entre parenthèses.

Il existe de nombreux exemples similaires. Vous en avez trouvé un.

D’après ce que je peux dire, le consensus est essentiellement que la règle devrait être ce que C ++ fait, mais ce que C n’a jamais officiellement adopté. C ++ rend fonctionnellement une expression entre parenthèses équivalente à l’expression non entre parenthèses, avec quelques exceptions explicites. Cela couvrirait toutes ces questions à la fois.

Donc techniquement, le type pourrait être considéré comme correct, mais c’est une interprétation trop ssortingcte de la norme que personne ne suit vraiment, car il est de notoriété publique que la norme est tout simplement fausse ici.

À partir de C99, 6.5.1, sur les expressions entre parenthèses:

Son type et sa valeur sont identiques à ceux de l’expression non mise entre parenthèses.

À première vue, il semblerait que cela soit en conflit avec la liste d’exceptions à laquelle vous faites référence (6.3.2.1):

Sauf s’il s’agit de l’opérande de l’opérateur sizeof ou de l’opérateur unary & , ou d’un littéral de chaîne utilisé pour initialiser un tableau, une expression de type “tableau de type” est convertie en une expression de type “pointeur vers type”. ..

Cependant, cette liste se situe dans le contexte des opérateurs / opérandes; les parenthèses ne semblent pas être considérées comme un opérateur (en fonction de la catégorisation impliquée par la structure de la section 6.5).