2017-08-15 3 views
4

C11 précise à la section 6.7, qui sont également des déclarations définitions:Quelles déclarations d'objet dans C provoquent la réservation du stockage (c'est-à-dire des définitions)?

Une définition d'un identificateur est une déclaration de cet identificateur que:
- pour un objet, provoque le stockage à réserver pour cet objet;
[...]

Je n'ai pas trouvé une liste complète dont les déclarations d'objets provoquent le stockage à réserver. Intuitivement, c'est clair pour moi, mais je n'ai pas pu obtenir cette information hors de la norme C11.

+0

Huh? Comme je l'ai lu, les * déclarations * ne font rien réserver. –

+1

tout ce qui n'utilise pas la classe de stockage 'extern'. –

+0

@EugeneSh. chaque définition est en même temps une déclaration, l'inverse n'est pas vrai. –

Répondre

4

Il n'y a pas de liste définitive, car la norme décrit simplement ce que sont les définitions et ce n'est pas dans un seul endroit. Je vais essayer de résumer ici. Je n'utilise le type int ici sans qualificatif (comme const) pour la cohérence.

  • Si vous ajoutez un initialiseur à une déclaration, il y a toujours une définition:

    int x = 1; 
    
  • Sans un initialiseur, les éléments suivants sont définitions quand ils sont dans champ de fonction :

    int x; 
    auto int x;  // auto is the default anyways 
    register int x; // register is just a hint, but would be "storage" as well 
    static int x;  // also reserves storage, but with static duration 
    
  • portée, les règles sont en fichier un peu plus compliqué; les éléments suivants sont définitions indicatives:

    int x; 
    static int x; 
    

    La formulation de la norme (§6.9.2p2) est:

    Une déclaration d'un identificateur pour un objet qui a une portée sans déposer un initialiseur, et sans spécificateur de classe de stockage ou avec le spécificateur de classe de stockage static, constitue une tentative de définition . Si une unité de traduction contient une ou plusieurs définitions provisoires pour un identifiant , et l'unité de traduction ne contient aucune définition externe pour cet identifiant, puis le comportement est exactement comme si l'unité de traduction contient une déclaration de portée de fichier de cet identifiant , la type composite à la fin de l'unité de traduction, avec un initialiseur égal à 0

    donc cela signifie que ils ont fini par « deviennent définitions » si elles ne se trouvent pas de se référer à une autre définition.

  • Avec la classe de stockage extern et sans initialiseur, vous n'avez pas une définition :

    extern int x;  // <- not a definition 
    

AFAIK, cela devrait être l'ensemble complet de règles. N'hésitez pas à modifier/commenter si j'ai oublié quelque chose.

+0

Il y a aussi le cas des déclarations '_Thread_local', qui semblent suivre des règles similaires à celles des définitions provisoires, seulement que la norme ne le dit qu'en 6.7.9. Probablement, ils ne veulent pas le lister comme une définition provisoire, car une telle déclaration '_Thread_local' déclare effectivement un objet par thread. –

+0

De toute évidence, ils ne sont pas des objets mais il vaut peut-être la peine de noter l'utilisation surchargée quelque peu confuse de 'extern' dans le contexte des instanciations de fonctions inline. Franchement, je ne comprends pas pourquoi la sémantique de plain 'inline' et 'extern inline' n'a pas été inversée. – doynax