332 votes

Comment utiliser correctement le mot-clé extern en C ?

Ma question est de savoir quand une fonction doit être référencée avec l'attribut extern en C.

Je ne vois pas dans quel cas il faut l'utiliser dans la pratique. Comme j'écris un programme, toutes les fonctions que j'utilise sont disponibles grâce aux fichiers d'en-tête que j'ai inclus. Alors pourquoi serait-il utile de extern pour accéder à quelque chose qui n'était pas exposé dans le fichier d'en-tête ?

Je pourrais être en train de penser à la façon dont extern est incorrecte, et si c'est le cas, veuillez me corriger.

Aussi Devriez-vous extern alors qu'il s'agit de la déclaration par défaut sans le mot-clé dans un fichier d'en-tête ?

1 votes

374voto

bluebrother Points 4224

extern modifie l'attelage. Avec le mot-clé, la fonction / variable est supposée être disponible ailleurs et la résolution est reportée à l'éditeur de liens.

Il y a une différence entre extern sur les fonctions et sur les variables.

Para variables il n'instancie pas la variable elle-même, c'est-à-dire qu'il n'alloue pas de mémoire. Cela doit être fait ailleurs. Il est donc important d'importer la variable depuis un autre endroit.

Para fonctions cela indique seulement au compilateur que le lien est extern. Comme il s'agit de la valeur par défaut (vous utilisez le mot-clé static pour indiquer qu'une fonction n'est pas liée à l'aide d'un lien externe), il n'est pas nécessaire de l'utiliser explicitement.

1 votes

Alors pourquoi la même chose extern est présente dans Git:un logiciel très populaire et moderne le vérifie : github.com/git/git/blob/master/strbuf.h

1 votes

Les K&R n'indiquent pas qu'il est obligatoire de déclarer une fonction comme "extern", mais cette réponse résout ma confusion !

0 votes

@rsjethani Je pense que c'est pour rendre le document plus strict et plus formaté.

251voto

lillq Points 4161

extern indique au compilateur que ces données sont définies quelque part et qu'elles seront connectées à l'éditeur de liens.

Avec l'aide des réponses données ici et en discutant avec quelques amis, voici l'exemple pratique d'une utilisation de extern .

Exemple 1 - pour montrer un écueil :

stdio.h :

int errno;

myCFile1.c :

#include <stdio.h>

// Code using errno...

myCFile2.c :

#include <stdio.h>

// Code using errno...

Si myCFile1.o y myCFile2.o sont liés, chacun des fichiers c a des copies séparées de errno . C'est un problème car les mêmes errno est censé être disponible dans tous les fichiers liés.

Exemple 2 - La solution.

stdio.h :

extern int errno;

stdio.c :

int errno;

myCFile1.c :

#include <stdio.h>

// Code using errno...

myCFile2.c :

#include <stdio.h>

// Code using errno...

Maintenant, si les deux myCFile1.o y MyCFile2.o sont liés par l'éditeur de liens, ils pointeront tous deux vers le même errno . Ainsi, la résolution de la mise en œuvre avec extern .

89 votes

Le problème n'est pas que les modules myCFile1 et myCFile2 ont une copie séparée de errno, c'est qu'ils exposent tous les deux un symbole appelé "errno". Lorsque l'éditeur de liens voit cela, il ne sait pas quel "errno" choisir, et il va donc se retirer avec un message d'erreur.

4 votes

Que signifie "linked by the linker" ? tout le monde utilise ce terme, je ne trouve pas de définition :(

9 votes

@MarcelFalliere Wiki ~ Le compilateur compile chaque fichier source séparément et crée un fichier objet pour chaque fichier source. L'éditeur de liens relie ces fichiers objets à un exécutable.

46voto

aib Points 18608

Il a déjà été dit que la extern est redondant pour les fonctions.

En ce qui concerne les variables partagées entre plusieurs unités de compilation, vous devez les déclarer dans un fichier d'en-tête avec le mot-clé extern, puis les définir dans un seul fichier source, sans le mot-clé extern. Le fichier source unique doit être celui qui partage le nom du fichier d'en-tête, pour des raisons de bonne pratique.

0 votes

@aib "redondant pour les fonctions", voir mon commentaire dans la réponse de bluebrother.

1 votes

Que faire si vous ne voulez exposer aucune des fonctions du fichier d'en-tête ? Ne serait-il pas préférable de déclarer la variable dans un fichier C et d'y accéder par extern dans un autre ; de laisser l'éditeur de liens résoudre le problème et de cacher le reste de l'en-tête.

16voto

Steve Melnikoff Points 1694

En C, extern est implicite pour les prototypes de fonction, car un prototype déclare une fonction qui est définie ailleurs. En d'autres termes, un prototype de fonction a un lien externe par défaut ; l'utilisation de extern est bien, mais il est redondant.

(Si un lien statique est nécessaire, la fonction doit être déclarée en tant que static à la fois dans son prototype et dans l'en-tête de la fonction, qui doivent normalement se trouver dans le même fichier .c).

9voto

tozak Points 49

Un très bon article que j'ai trouvé sur le site extern ainsi que les exemples : http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

Bien que je ne sois pas d'accord sur le fait que l'utilisation de extern dans les déclarations de fonctions est redondant. C'est censé être un paramètre du compilateur. Je recommande donc d'utiliser l'option extern dans les déclarations de fonctions lorsque cela est nécessaire.

7 votes

J'ai lu l'article de geeksforgeeks.org avant de venir ici, mais je l'ai trouvé assez mal écrit. Outre les lacunes grammaticales et syntaxiques, il utilise beaucoup de mots pour exprimer plusieurs fois la même chose et passe sous silence les informations essentielles. Par exemple, dans l'exemple 4, le fichier 'somefile.h' est soudainement inclus, mais rien n'est dit à son sujet, si ce n'est que : "Supposons que somefile.h a la définition de var". Or, l'information que nous "supposons" est justement celle que je recherche. Malheureusement, aucune des réponses de cette page n'est meilleure.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X