web-dev-qa-db-fra.com

Pourquoi `int;` compile bien en C, mais pas en C ++?

Considérez le programme suivant (voir la démo en direct ici ).

#include <stdio.h>
int main(void)
{
      int ;  // Missing variable name
      puts("Surprise");
}

Mon compilateur, gcc 4.8.1, donne l'avertissement ci-dessous:

[Avertissement] nom de type inutile dans une déclaration vide [activé par défaut]

Pourquoi compile-t-il bien? Ne devrais-je pas obtenir une erreur de compilation? g ++ 4.8.1 donne l'erreur suivante lorsque je le compile en tant que programme C++:

La déclaration [error] ne déclare rien [-fpermissive]

57
Destructor

La norme C dit

Une déclaration autre qu'une déclaration static_assert doit déclarer au moins un déclarant (autre que les paramètres d'une fonction ou les membres d'une structure ou d'union), une balise ou les membres d'une énumération.

C++ dit

Dans une déclaration simple, la liste facultative init-declarator-list ne peut être omise que lors de la déclaration d'une classe (article 9) ou d'une énumération.

Une violation de cela dans l'une ou l'autre langue nécessite un diagnostic. Les normes ne parlent pas d'erreurs ou d'avertissements du compilateur. Un avertissement est un diagnostic.

48
n.m.

Votre code est illégal (c'est-à-dire erroné, mal formé, violant les contraintes) en C et C++. La raison pour laquelle vous obtenez un "avertissement" dans une langue et une "erreur" dans une autre n'est qu'une bizarrerie de votre compilateur et de sa configuration. Après tout, aucune langue ne fait vraiment de différence formelle entre "avertissements" et "erreurs". GCC sous ses paramètres par défaut se trouve être plus permissif en mode C (principalement pour des raisons historiques).

Utilisation -pedantic-errors dans GCC, et vous obtiendrez également une "erreur" dans le code C. (Notez que -pedantic-errors ne transforme pas simplement aveuglément tous les "avertissements" en "erreurs". Il tente de signaler uniquement les violations de contraintes comme des "erreurs".)

34
AnT

La syntaxe de la déclaration est définie comme (en omettant init-declarator-list et init-declarator):

C11 6.7 Déclarations

declaration:
    declaration-specifiers init-declarator-list opt ;
    static_assert-declaration
declaration-specifiers:
    storage-class-specifier declaration-specifiers opt
    type-specifier declaration-specifiers opt
    type-qualifier declaration-specifiers opt
    function-specifier declaration-specifiers opt
    alignment-specifier declaration-specifiers opt

Notez que declaration-specifiers est défini récursivement, mais chacun avec un opt indique qu'il est facultatif.

En outre, l'article 6 suivant stipule:

Les spécificateurs de déclaration se composent d'une séquence de spécificateurs qui indiquent le lien, la durée de stockage et une partie du type des entités que les déclarants désignent. La liste initdeclarator-list est une séquence de déclarateurs séparés par des virgules, chacun pouvant avoir des informations de type supplémentaires, ou un initialiseur, ou les deux. Les déclarateurs contiennent les identifiants (le cas échéant) en cours de déclaration.

Notez les mots le cas échéant.

18
Yu Hao