Partager via


extern (C++)

Le mot clé extern peut être appliqué à une déclaration de variable globale, de fonction ou de modèle. Cela spécifie que le symbole a une liaison externe. Pour plus d’informations sur la liaison et sur les raisons pour lesquelles l’utilisation de variables globales est déconseillée, consultez Unités de traduction et liaison.

Le mot clé extern a quatre significations selon le contexte :

  • Dans une déclaration de variable globale non const, extern spécifie que la variable ou la fonction est définie dans une autre unité de traduction. Le mot clé extern doit être appliqué dans tous les fichiers, à l’exception de celui où la variable est définie.

  • Dans une déclaration de variable const, cela spécifie que la variable a une liaison externe. Le mot clé extern doit être appliqué à toutes les déclarations dans tous les fichiers. (Les variables const globales ont une liaison interne par défaut.)

  • extern "C" spécifie que la fonction est définie ailleurs, et utilise la convention d’appel du langage C. Le modificateur extern "C" peut également être appliqué à plusieurs déclarations de fonction dans un bloc.

  • Dans une déclaration de modèle, extern spécifie que le modèle a déjà été instancié ailleurs. extern indique au compilateur qu’il peut réutiliser l’autre instanciation, au lieu d’en créer une autre à l’emplacement actuel. Pour plus d’informations sur cette utilisation de extern, consultez Instanciation explicite.

Liaison extern pour les variables globales non const

Quand l’éditeur de liens voit extern devant une déclaration de variable globale, il recherche la définition dans une autre unité de traduction. Les déclarations de variables non const à l’étendue globale sont externes par défaut. Appliquez uniquement extern aux déclarations qui ne fournissent pas la définition.

//fileA.cpp
int i = 42; // declaration and definition

//fileB.cpp
extern int i;  // declaration only. same as i in FileA

//fileC.cpp
extern int i;  // declaration only. same as i in FileA

//fileD.cpp
int i = 43; // LNK2005! 'i' already has a definition.
extern int i = 43; // same error (extern is ignored on definitions)

Liaison extern pour les variables globales const

Une variable globale const a une liaison interne par défaut. Si vous voulez que la variable ait une liaison externe, appliquez le mot-clé extern à la définition, ainsi qu’à toutes les autres déclarations dans d’autres fichiers :

//fileA.cpp
extern const int i = 42; // extern const definition

//fileB.cpp
extern const int i;  // declaration only. same as i in FileA

Liaison extern constexpr

Dans Visual Studio 2017 15.3 et les versions antérieures, le compilateur traitait toujours une variable constexpr comme ayant une liaison interne, même si cette variable était marquée extern. Dans Visual Studio 2017 15.5 et les versions ultérieures, le commutateur de compilateur /Zc:externConstexpr permet d’obtenir un comportement approprié conforme aux standards. À terme, cette option deviendra la valeur par défaut. L’option /permissive- n’active pas /Zc:externConstexpr.

extern constexpr int x = 10; //error LNK2005: "int const x" already defined

Si un fichier d’en-tête contient une variable déclarée extern constexpr, elle doit être marquée __declspec(selectany) pour que ses déclarations dupliquées soient correctement combinées :

extern constexpr __declspec(selectany) int x = 10;

Déclarations de fonction extern "C" et extern "C++"

En C++, quand extern est utilisé avec une chaîne, il spécifie que les conventions de liaison d’un autre langage sont utilisées pour le ou les déclarateurs. Les fonctions et les données C sont accessibles uniquement si elles ont été déclarées au préalable comme ayant une liaison C. Toutefois, elles doivent être définies dans une unité de traduction compilée séparément.

Microsoft C++ prend en charge les chaînes "C" et "C++" dans le champ de littéral de chaîne. Tous les fichiers include standard utilisent la syntaxe extern "C" pour permettre l’utilisation des fonctions de bibliothèque runtime dans les programmes C++.

Exemple

L’exemple suivant montre comment déclarer les noms qui ont une liaison C :

// Declare printf with C linkage.
extern "C" int printf(const char *fmt, ...);

//  Cause everything in the specified
//  header files to have C linkage.
extern "C" {
    // add your #include statements here
#include <stdio.h>
}

//  Declare the two functions ShowChar
//  and GetChar with C linkage.
extern "C" {
    char ShowChar(char ch);
    char GetChar(void);
}

//  Define the two functions
//  ShowChar and GetChar with C linkage.
extern "C" char ShowChar(char ch) {
    putchar(ch);
    return ch;
}

extern "C" char GetChar(void) {
    char ch;
    ch = getchar();
    return ch;
}

// Declare a global variable, errno, with C linkage.
extern "C" int errno;

Si une fonction a plusieurs spécifications de liaison, elles doivent être compatibles. Il est erroné de déclarer des fonctions comme ayant à la fois une liaison C et C++. De plus, si deux déclarations relatives à une fonction ont lieu dans un programme, l’une avec une spécification de liaison, et l’autre sans, la déclaration avec la spécification de liaison doit être la première. Toutes les déclarations redondantes de fonctions qui ont déjà une spécification de liaison sont affectées de la liaison spécifiée dans la première déclaration. Par exemple :

extern "C" int CFunc1();
...
int CFunc1();            // Redeclaration is benign; C linkage is
                         //  retained.

int CFunc2();
...
extern "C" int CFunc2(); // Error: not the first declaration of
                         //  CFunc2;  cannot contain linkage
                         //  specifier.

À partir de Visual Studio 2019, quand /permissive- est spécifié, le compilateur vérifie que les déclarations des paramètres des fonctions extern "C" correspondent également. Vous ne pouvez pas surcharger une fonction déclarée en tant que extern "C". À partir de Visual Studio 2019 version 16.3, vous pouvez remplacer cette vérification en utilisant l’option de compilateur /Zc:externC- après l’option /permissive-.

Voir aussi

Mots clés
Unités de traduction et liaison
Spécificateur de classe de stockage extern en C
Comportement des identificateurs en C
Liaison en C