Pourquoi une variable ne peut pas être définie deux fois dans 2 fichiers en C

Pourquoi je ne peux pas avoir un int; dans 2 fichiers C. J’ai l’intention de combiner les deux pour rendre exécutable. Je sais par expérience que je ne peux pas, mais je veux trouver où la norme C99 dit cela et scelle ma compréhension.

Je lis la norme ISO C99 de http://www.open-std.org/jtc1/sc22/wg…docs/n1256.pdf . On dit à la page 42:

6.2.2 Liens d’identifiants

1 Un identificateur déclaré dans plusieurs scopes ou dans la même scope plusieurs fois peut être appelé à faire référence au même object ou à la même fonction par un processus appelé linkage.Il existe trois types de liaison: externe, interne et aucune.

2 Dans l’ensemble des unités de traduction et des bibliothèques constituant un programme complet, chaque déclaration d’un identificateur particulier avec une liaison externe désigne le même object ou la même fonction. Au sein d’une unité de traduction, chaque déclaration d’un identifiant avec une liaison interne désigne le même object ou la même fonction. Chaque déclaration d’un identifiant sans lien dénote une entité unique.

3 Si la déclaration d’un identificateur de scope de fichier pour un object ou une fonction contient le spéci fi cateur de classe de stockage static, cet identificateur est associé à un lien interne.

4 Pour un identi fi cateur déclaré avec le spéci fi cateur de classe de stockage extern dans une scope dans laquelle une déclaration antérieure de cet identi fi cateur est visible, si la déclaration antérieure spéci fi e un lien interne ou externe, le lien de l’identi fi cateur lors de la déclaration ultérieure est le même que le lien spécifié dans la déclaration préalable. Si aucune déclaration préalable n’est visible ou si la déclaration antérieure ne spécifie aucun lien, l’identificateur est associé à un lien externe.

5 Si la déclaration d’un identifiant pour une fonction n’a pas de spéci fi cateur de classe de stockage, son lien est déterminé exactement comme s’il avait été déclaré avec le spéci fi cateur de classe de stockage extern.Si la déclaration d’un identi fi cateur pour un object a une scope de fichier et aucun stockage spéci fi cateur de classe, sa liaison est externe.

Après avoir lu ceci, il semble que si je déclare une variable telle que say int a; dans 2 fichiers source. alors les deux ont un lien externe selon les règles 5 et 4. et ensuite selon la règle 2, les deux doivent faire référence au même object. Alors pourquoi le compilateur crée-t-il un problème? Où dans la norme il est suggéré que nous ne pouvons pas déclarer comme ceci dans 2 fichiers sources et cela devrait générer une erreur de compilation. Premièrement, où dans la norme, il est dit que int a est une définition, et ensuite où il est dit que 2 instances de définitions ne sont pas acceptables. Je sais que mon expérience ne me le permet pas, mais cela me serait très utile si je pouvais trouver cela dans la norme et sceller ma compréhension.

Les extraits suivants de la norme combinés correspondent-ils à cette règle? ou j’ai manqué cette colle? :

Une déclaration spécifie l’interprétation et les atsortingbuts d’un ensemble d’identifiants. Une définition d’un identifiant est une déclaration pour cet identifiant qui: —pour un object, le stockage est réservé à cet object; —Pour une fonction, inclut le corps de la fonction; – pour une constante d’énumération ou un nom typedef, est la (seule) déclaration de l’identificateur.

Comme indiqué au paragraphe 5.1.1.1, l’unité de texte de programme après prétraitement est une unité de traduction, qui consiste en une séquence de déclarations externes. Celles-ci sont qualifiées d ‘”externes” car elles apparaissent en dehors de toute fonction (et ont donc une scope de fichier). Comme indiqué dans la section 6.7, une déclaration qui entraîne également la réservation du stockage pour un object ou une fonction nommé par l’identificateur est une définition.

Une définition externe est une déclaration externe qui est également une définition d’une fonction (autre qu’une définition en ligne) ou d’un object. Si un identi fi cateur déclaré avec une liaison externe est utilisé dans une expression (autre que dans l’opérande d’un opérateur sizeof dont le résultat est une constante entière), il doit exister une définition externe exacte pour l’identificateur dans le programme entier. sinon, il n’y en aura pas plus d’un.

Merci.

Je pense que vous avez besoin de 6.9.2 / 2:

La déclaration d’un identifiant pour un object ayant une scope de fichier sans initialiseur, et sans spécificateur de classe de stockage ou avec le spécificateur de classe de stockage static , constitue une définition provisoire . Si une unité de traduction contient une ou plusieurs définitions provisoires pour un identificateur et que l’unité de traduction ne contient aucune définition externe pour cet identificateur, le comportement est exactement comme si l’unité de traduction contenait une déclaration de la scope du fichier de cet identificateur, avec le type composite as de la fin de l’unité de traduction, avec un initialiseur égal à 0.

et 6.9 / 5:

Une définition externe est une déclaration externe qui est également une définition d’une fonction (autre qu’une définition en ligne) ou d’un object. Si un identificateur déclaré avec une liaison externe est utilisé dans une expression (autre que dans l’opérande d’un opérateur sizeof dont le résultat est une constante entière), il doit exister une définition externe pour l’identificateur dans le programme entier. sinon, il n’y en aura pas plus d’un.

Fondamentalement, int a; est une définition provisoire . Vous pouvez avoir plusieurs définitions provisoires dans une même unité de traduction, mais l’effet est identique à une définition externe non provisoire (par exemple, quelque chose comme int a = 0; ). Avoir plus qu’une définition d’un object avec une liaison externe dans un programme est une violation de 6.9 / 5.

Noter qu’il s’agit d’une “extension commune” permettant plusieurs définitions externes d’un object, à condition qu’au moins une seule soit initialisée et que les définitions concordent (voir J.5.11).