2010-05-15 3 views
46

Pourquoi extern int n ne compile pas lorsque n est déclaré (dans un fichier différent) static int n, mais fonctionne lorsqu'il est déclaré int n? (Ces deux déclarations étaient à la portée du fichier.)Pourquoi extern ne va-t-il pas à une variable statique?

Fondamentalement, pourquoi int n dans la portée de fichier n'est pas la même que static int n dans la même étendue? Est-ce seulement par rapport à extern? Si oui, qu'en est-il de extern?

Répondre

97

L'objectif entier et entier de static est de déclarer qu'une variable est privée au fichier source qu'il est déclaré dans. Ainsi, il fait précisément son travail en empêchant une connexion d'un externe.

Gardez à l'esprit qu'il ya quatre saveurs de définition de la variable fichier entier:

  1. int blah = 0; - bla est défini dans ce fichier et accessible à partir d'autres fichiers. Les définitions dans d'autres fichiers sont des doublons et conduiront à des erreurs.
  2. extern int blah; - blah doit être défini ailleurs et référencé à partir de ce fichier.
  3. int blah; - Ceci est l'équivalent moral de FORTRAN COMMON. Vous pouvez avoir n'importe quel nombre de ces fichiers, et ils sont tous résolus par l'éditeur de liens à un partagé int. (*)
  4. static int blah; (éventuellement avec un initialiseur) - Ceci est statique. C'est complètement privé dans ce fichier. Il n'est pas visible aux externes dans d'autres fichiers, et vous pouvez avoir de nombreux fichiers différents qui déclarent tous static TYPE blah;, et ils sont tous différents.

Pour les puristes du public: 'file' = unité de compilation.

Notez que les fonctions internes statiques (pas à portée de fichier) sont encore plus étroitement délimitées: si deux fonctions déclarent static int bleh = 0; même dans le même fichier, elles ne sont pas liées. (*): Pour ceux qui ne vous sont pas familiers: dans le modèle habituel, une unité de compilation doit définir une variable globale, et d'autres peuvent la référencer. Il «vit» dans cette unité de compilation. Dans le cas (3) ci-dessus, aucun fichier (ou tous les fichiers) ne le définit. Si deux fichiers indiquent int blah = 0;, l'éditeur de liens se plaindra de plusieurs définitions. Si deux fichiers disent int blah; l'éditeur de liens crée gaiement un seul int global et provoque tout le code s'y référer.

+0

qu'appelle-t-on alors (dans la portée du fichier), en termes de spécificateurs de stockage? –

+0

@bmargulies: Au niveau de la portée du fichier, vous voulez dire? Parce qu'à la portée de la fonction, une variable statique est celle qui conserve sa valeur après le retour des fonctions, et à la portée de la classe, un membre statique a une seule instance disponible pour tous les objets. – mingos

+0

Clarifié par l'édition, je confiance. – bmargulies

5

En C standard, il existe deux étendues pour les variables déclarées en dehors d'une fonction. Une variable static est uniquement visible à l'intérieur de l'unité de compilation (c'est-à-dire, le fichier) qui l'a déclarée, et les variables non statiques sont visibles dans tout le programme. Une déclaration extern indique que l'emplacement de la variable n'est pas encore connu, mais sera trié par l'éditeur de liens; c'est compatible avec les variables non-statiques, mais extern static est juste une conversation folle!

Bien sûr, en pratique il y a d'autres visibilités ces jours-ci. En particulier, il existe maintenant des niveaux de portée entre celui d'un seul fichier source et celui d'un programme entier; le niveau d'une seule bibliothèque partagée est utile (paramétrable via des mécanismes tels que les attributs de fonction GCC). Mais ce n'est qu'une variation sur le thème des variables non statiques; static conserve la même interprétation que précédemment.

0

Selon la documentation MSDN:

When modifying a variable, the static keyword specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless another value is specified. When modifying a variable or function at file scope, the static keyword specifies that the variable or function has internal linkage (its name is not visible from outside the file in which it is declared).

http://msdn.microsoft.com/en-us/library/s1sb61xd(v=vs.80).aspx: Juin 2013

1

IV.C: 2: 1: erreur: multiples classes de stockage dans la déclaration spécificateurs extern static int i; C'est ce que nous obtenons en essayant d'externer une variable statique. ^

Déclarer extern static int i; - est analogue à la déclaration float int i; Vous ne pouvez pas avoir float et int apparaissent dans la même déclaration droite? De même, vous ne pouvez pas avoir extern et static dans la même déclaration.

Questions connexes