2010-02-27 5 views
1

AFAIK, le mot-clé extern doit être utilisé pour la déclaration et aucune valeur ne peut être associée à la variable déclarée avec le mot-clé extern. Mais en supposant que j'écris une instruction commeDoute liée à l'utilisation des mots-clés externes

extern int i = 10; 

Le compilateur doit-il signaler une erreur pour le même? J'ai vu des compilateurs être tolérant et ignorant cela? Pourquoi cela est-il ainsi? Que dit la norme 'C' à ce sujet?

EDIT: @All, Merci pour les réponses. J'ai encore un doute. Supposons que j'ai la définition de cette variable sans la liaison externe dans un autre fichier disons a.c et j'ajoute cette déclaration dans b.c. Est-il toujours correct pour le compilateur de ne pas signaler une erreur? Cela vient-il en redéfinition?

+0

Non, car il s'agit en fait d'une définition et non d'une déclaration. – Clifford

+0

LLVM lève un avertissement: "variable externe a un initialiseur" – Binarian

Répondre

6

C'est une syntaxe valide, il y a même un exemple essentiellement identique dans la norme C99. (Voir §6.9.2-4.)

Il est vrai que les exemples ne sont pas normatifs mais je crois que c'était une syntaxe légale. Le compilateur produira souvent un avertissement, car il n'effectue vraiment rien.

4 EXEMPLE 1

int i1 = 1;    // definition, external linkage 
static int i2 = 2;  // definition, internal linkage 
extern int i3 = 3;  // definition, external linkage 
int i4;     // tentative definition, external linkage 
static int i5;   // tentative definition, internal linkage 
int i1;     // valid tentative definition, refers to previous 
int i2;     // 6.2.2 renders undefined, linkage disagreement 
int i3;     // valid tentative definition, refers to previous 
int i4;     // valid tentative definition, refers to previous 
int i5;     // 6.2.2 renders undefined, linkage disagreement 
extern int i1;   // refers to previous, whose linkage is external 
extern int i2;   // refers to previous, whose linkage is internal 
extern int i3;   // refers to previous, whose linkage is external 
extern int i4;   // refers to previous, whose linkage is external 
extern int i5;   // refers to previous, whose linkage is internal 
+0

Si cela ne fonctionne vraiment pas, pourquoi est-il autorisé? – Jay

+0

Beaucoup de mots-clés et la syntaxe se trouvent être l'interprétation par défaut dans un endroit donné. Par exemple, dans une fonction 'int i;' et 'auto int i;' sont la même définition. L'ajout de 'auto' n'effectue rien de particulier, ce qui permet une utilisation cohérente du spécificateur de classe de stockage. – DigitalRoss

0

Le mot-clé extern indique que la variable donnée est attribué à un autre module. Il n'a rien à voir avec accès à cette variable. Il est parfaitement légal d'attribuer à une variable externe.

+0

Premièrement, la variable dans l'OP est allouée dans * ce * module, puisque la déclaration dans l'OP est en fait une * définition *. 'extern' ne dit pas que quelque chose est" dans un module différent ". Cela donne juste un lien externe. Deuxièmement, il n'y a pas de cession dans le PO. C'est une initialisation, pas une affectation. – AnT

+0

Notez qu'il s'agit d'un exemple d'initialisation non affectée. – Clifford

0

Le but du mot-clé extern est de donner à l'entité le couplage externe. Qu'il soit utilisé dans une déclaration dans une ou une définition ne fait aucune différence. Il n'y a absolument aucune erreur dans le code que vous avez posté.

Si vous préférez penser en termes de « l'exportation par rapport à l'importation », puis extern mot-clé appliqué à une déclaration non-définition signifie que nous sommes importation une entité définie dans une autre unité de traduction. Lorsque extern mot-clé appliqué à une définition, cela signifie que nous sommes exportant cette entité doit être utilisé par d'autres unités de traduction. (Bien qu'il soit intéressant de noter que «exporter ou importer» n'est pas exactement une façon standard de penser au concept de couplage en C.)

La raison pour laquelle vous ne verrez pas très souvent le mot-clé utilisé dans les définitions est parce que dans Les définitions de portée de fichier C ont un lien externe par défaut.Donc, écrire

extern int i = 10; 

est valide, mais redondant, car il est équivalent à la plaine

int i = 10; 

Pourtant, de temps à autre dans le code réel que vous pouvez voir les gens en utilisant ce mot-clé avec les déclarations de fonction et définitions , même si elle est également superflue

extern void foo(int i); /* `extern` is superfluous */ 
... 
extern void foo(int i) /* `extern` is superfluous */ 
{ 
    /* whatever */ 
} 
+0

J'ai décliné cette erreur par erreur, et il était trop tard pour la corriger. Pour rétablir l'équilibre, j'ai trouvé une autre réponse que vous avez aimée et améliorée. Pas qu'il semble que vous en ayez besoin;) Toutes mes excuses. – Clifford

4

Le code suivant;

extern int i ; 

déclare une variable i, mais n'instancier pas. S'il n'est pas également défini dans la même unité de compilation, l'éditeur de liens tentera de le résoudre à partir des fichiers objets et des bibliothèques qui composent l'exécutable final.

Cependant votre exemple:

extern int i = 10 ; 

l'objet initialise, et donc doit aussi instancier. Dans ce cas, le mot clé extern est redondant car l'objet est initialisé dans la même unité de compilation (en fait, la même instruction). Il est équivalent à:

extern int i ; // redundant 
int i = 10 ; 

Bien que dans ce dernier exemple, le mot-clé extern est redondant, il est exactement équivalent à ce que vous avez quand une variable globale est déclarée dans un fichier d'en-tête et instancié dans un fichier source qui inclut également cet en-tête (comme il se doit, pour permettre au compilateur d'effectuer une vérification de type).

Vous pouvez tester cela comme suit:

extern int i ; 
int main() 
{ 
    i = 10 ; 
} 

ci-dessus provoque une erreur de liaison pour la variable non résolue i. Considérant que:

extern int i = 10 ; 
int main() 
{ 
    i = 10 ; 
} 

liera sans problème.