web-dev-qa-db-fra.com

Pourquoi ne fait-il pas de lien externe vers une variable statique?

Pourquoi extern int n pas de compilation lorsque n est déclaré (dans un fichier différent) static int n, mais fonctionne une fois déclaré int n? (Ces deux déclarations étaient à portée de fichier.)

Fondamentalement, pourquoi int n dans la portée du fichier n'est pas identique à static int n dans le même périmètre? Est-ce uniquement par rapport à l'externe? Si oui, qu'en est-il que je manque à l'extérieur?

54
Jared Pochtar

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

Gardez à l'esprit qu'il existe quatre variantes de définition de variable de portée de fichier:

  1. int blah = 0; - blah est défini dans ce fichier et accessible à partir d'autres fichiers. Les définitions dans d'autres fichiers sont des doublons et entraîneront des erreurs.
  2. extern int blah; - blah doit être défini ailleurs et est référencé à partir de ce fichier.
  3. int blah; - C'est l'équivalent moral de FORTRAN COMMON. Vous pouvez en avoir un certain nombre dans des fichiers, et ils sont tous résolus par l'éditeur de liens vers un int partagé. (*)
  4. static int blah; (éventuellement avec un initialiseur) - C'est statique. Il est totalement privé de ce fichier. Il n'est pas visible par les 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 statiques internes (pas à la portée du fichier) sont encore plus limitées: si deux fonctions déclarent static int bleh = 0; même dans le même fichier, ils ne sont pas liés.

(*): pour ceux d'entre vous qui ne 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 indiquent int blah; l'éditeur de liens crée joyeusement un seul int global et fait que tout le code s'y réfère.

114
bmargulies

Dans la norme C, il existe deux étendues pour les variables déclarées en dehors d'une fonction. Une variable static n'est visible qu'à 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; il est compatible avec les variables non statiques, mais extern static est juste un discours fou!

Bien sûr, dans la pratique, il y a d'autres visibilités de nos jours. En particulier, il existe maintenant des niveaux de portée entre celui d'un fichier source unique et d'un programme entier; le niveau d'une bibliothèque partagée unique est utile (réglable par des mécanismes comme 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 qu'auparavant.

6
Donal Fellows

Selon la documentation MSDN:

Lors de la modification d'une variable, le mot clé statique spécifie que la variable a une durée statique (elle est allouée au début du programme et désallouée à la fin du programme) et l'initialise à 0 sauf si une autre valeur est spécifiée. Lors de la modification d'une variable ou d'une fonction à la portée du fichier, le mot clé statique spécifie que la variable ou la fonction a un lien interne (son nom n'est pas visible de l'extérieur du fichier dans lequel il est déclaré).

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

1
felknight

iv.c: 2: 1: erreur: plusieurs classes de stockage dans les spécificateurs de déclaration extern static int i; ^

C'est ce que nous obtenons en tentant d'externaliser une variable statique. Déclaration de statique externe int i; - est analogue à la déclaration float int i; Vous ne pouvez pas faire apparaître float et int dans la même déclaration, n'est-ce pas? De même, vous ne pouvez pas avoir extern et static dans la même déclaration.

1
Gautham