Namensräume
Varianten
Aktionen

Sprachbindung

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Ermöglicht die Bindung zwischen Programmeinheiten, die in verschiedenen Programmiersprachen geschrieben sind.

Dies kann auch verwendet werden, um eine Deklaration von ihrem Modul zu trennen. Siehe Modulbesitz.

(seit C++20)
extern string-literal { declaration-seq (optional) } (1)
extern string-literal declaration (2)
1) Wendet die Sprachspezifikation string-literal auf alle Funktionstypen, Funktionsnamen mit externer Bindung und Variablen mit externer Bindung an, die in declaration-seq deklariert sind.
2) Wendet die Sprachspezifikation string-literal auf eine einzelne Deklaration oder Definition an.
string-literal - ein nicht ausgewertetes String-Literal, das die erforderliche Sprachbindung benennt
declaration-seq - eine Sequenz von Deklarationen, die verschachtelte Bindungsspezifikationen enthalten kann
Deklaration - eine Deklaration

Inhalt

[bearbeiten] Erklärung

Jeder Funktionstyp, jeder Funktionsname mit externer Bindung und jeder Variablenname mit externer Bindung hat eine Eigenschaft namens Sprachbindung. Sprachbindung kapselt die Menge der Anforderungen, die zur Verknüpfung mit einer in einer anderen Programmiersprache geschriebenen Programmeinheit erforderlich sind: Aufrufkonvention, Algorithmus für Namensverknüpfung (Namensverschönerung) usw.

Nur zwei Sprachbindungen werden garantiert unterstützt

  1. "C++", die Standard-Sprachbindung.
  2. "C", was die Verknüpfung mit in der C-Programmiersprache geschriebenen Funktionen ermöglicht und die Definition von Funktionen in einem C++-Programm, die von in C geschriebenen Einheiten aufgerufen werden können.
extern "C"
{
    int open(const char *path_name, int flags); // C function declaration
}
 
int main()
{
    int fd = open("test.txt", 0); // calls a C function from a C++ program
}
 
// This C++ function can be called from C code
extern "C" void handler(int)
{
    std::cout << "Callback invoked\n"; // It can use C++
}

Da die Sprachbindung Teil jedes Funktionstyps ist, behalten auch Funktionszeiger die Sprachbindung bei. Die Sprachbindung von Funktionstypen (die die Aufrufkonvention repräsentiert) und die Sprachbindung von Funktionsnamen (die die Namensverknüpfung repräsentiert) sind voneinander unabhängig

extern "C" void f1(void(*pf)()); // declares a function f1 with C linkage,
                             // which returns void and takes a pointer to a C function
                             // which returns void and takes no parameters
 
extern "C" typedef void FUNC(); // declares FUNC as a C function type that returns void
                                // and takes no parameters
 
FUNC f2;            // the name f2 has C++ linkage, but its type is C function
extern "C" FUNC f3; // the name f3 has C linkage and its type is C function void()
void (*pf2)(FUNC*); // the name pf2 has C++ linkage, and its type is
                    // "pointer to a C++ function which returns void and takes one
                    // argument of type 'pointer to the C function which returns void
                    // and takes no parameters'"
 
extern "C"
{
    static void f4(); // the name of the function f4 has internal linkage (no language)
                      // but the function's type has C language linkage
}

Wenn zwei Deklarationen einer Entität ihr unterschiedliche Sprachbindungen geben, ist das Programm schlecht formuliert; keine Diagnose ist erforderlich, wenn keine Deklaration von der anderen erreichbar ist. Eine Neudeklaration einer Entität ohne Bindungsspezifikation erbt die Sprachbindung der Entität und ihres Typs (falls vorhanden).

extern "C" int f();
extern "C++" int f(); // Error: different language linkages
 
extern "C" int g();
int g(); // OK, has C language linkage
 
int h(); // has C++ language linkage by default
extern "C" int h(); // Error: different language linkages

[bearbeiten] Sonderregeln für "C"-Bindung

Wenn Klassenmitglieder, friend-Funktionen mit einer nachfolgenden requires Klausel,(seit C++20) oder nicht-statische Member-Funktionen in einem "C"-Sprachblock vorkommen, bleibt die Bindung ihrer Typen "C++" (aber Parametertypen, falls vorhanden, bleiben "C")

extern "C"
{
    class X
    {
        void mf();           // the function mf and its type have C++ language linkage
        void mf2(void(*)()); // the function mf2 has C++ language linkage;
                             // the parameter has type “pointer to C function”
    };
}
 
template<typename T>
struct A { struct B; };
 
extern "C"
{
    template<typename T>
    struct A<T>::B
    {
        friend void f(B*) requires true {} // C language linkage ignored
    };
}
 
namespace Q
{
    extern "C" void f(); // not ill-formed
}

Sei C eine Deklaration, die eine Funktion oder Variable mit "C"-Sprachbindung deklariert. Wenn eine andere Deklaration D eine Entität mit demselben Namen deklariert und eine der folgenden Bedingungen erfüllt, deklarieren C und D dieselbe Entität

  • D deklariert eine Variable, die zum globalen Geltungsbereich gehört.
  • Wenn C eine Variable deklariert, deklariert D ebenfalls eine Variable.
  • Wenn C eine Funktion deklariert, deklariert D ebenfalls eine Funktion.

Im Gegensatz zu regulären Neudeklarationen können C und D unterschiedliche Ziel-Geltungsbereiche haben

extern "C"
{
    int x;
    int f();
    int g() { return 1; }
}
 
namespace A
{
    int x;                // Error: redefines “x”
    int f();              // OK, redeclares “f”
    int g() { return 1; } // Error: redefines “g”
}

Die Beschränkungen solcher Deklarationen gelten jedoch weiterhin, was bedeutet, dass sie entweder beide Funktionen oder beide Variablen deklarieren sollten und die deklarierten Entitäten denselben Typ haben müssen

namespace A
{
    extern "C" int x();
    extern "C" int y();
}
 
int x; // Error: redeclares “x” as a different kind of entity
 
namespace B
{
    void y(); // Error: redeclares “y” with a different type
}

[bearbeiten] Hinweise

Sprachspezifikationen dürfen nur im Namespace-Geltungsbereich erscheinen.

Die geschweiften Klammern der Sprachspezifikation bilden keinen Geltungsbereich.

Wenn Sprachspezifikationen verschachtelt sind, ist die innerste Spezifikation diejenige, die wirksam ist.

Eine Deklaration, die direkt in einer Sprachbindungsspezifikation enthalten ist, wird so behandelt, als enthielte sie den extern Spezifikator für die Bestimmung der Bindung des deklarierten Namens und ob es sich um eine Definition handelt.

extern "C" int x; // a declaration and not a definition
// The above line is equivalent to extern "C" { extern int x; }
 
extern "C" { int x; } // a declaration and definition
 
extern "C" double f();
static double f(); // error: linkage conflict
 
extern "C" static void g(); // error: linkage conflict

extern "C" ermöglicht das Einbinden von Header-Dateien mit Deklarationen von C-Bibliotheksfunktionen in ein C++-Programm. Wenn dieselbe Header-Datei jedoch mit einem C-Programm geteilt wird, muss extern "C" (das in C nicht erlaubt ist) mit einem entsprechenden #ifdef ausgeblendet werden, typischerweise __cplusplus

#ifdef __cplusplus
extern "C" int foo(int, int); // C++ compiler sees this
#else
int foo(int, int);            // C compiler sees this
#endif

Der einzige moderne Compiler, der Funktionstypen mit "C"- und "C++"-Sprachbindungen unterscheidet, ist Oracle Studio. Andere erlauben keine Überladungen, die sich nur in der Sprachbindung unterscheiden, einschließlich der vom C++-Standard erforderlichen Überladungsmengen (std::qsort, std::bsearch, std::signal, std::atexit und std::at_quick_exit): GCC-Fehler 2316, Clang-Fehler 6277, CWG-Problem 1555.

extern "C"   using c_predfun   = int(const void*, const void*);
extern "C++" using cpp_predfun = int(const void*, const void*);
 
// ill-formed, but accepted by most compilers
static_assert(std::is_same<c_predfun, cpp_predfun>::value,
              "C and C++ language linkages shall not differentiate function types.");
 
// following declarations do not declare overloads in most compilers
// because c_predfun and cpp_predfun are considered to be the same type
void qsort(void* base, std::size_t nmemb, std::size_t size, c_predfun*   compar);
void qsort(void* base, std::size_t nmemb, std::size_t size, cpp_predfun* compar);

[bearbeiten] Schlüsselwörter

extern

[bearbeiten] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 4 C++98 Namen mit interner Bindung können Sprachbindungen haben beschränkt auf Namen mit externer Bindung
CWG 341 C++98 Eine Funktion mit "C"-Sprachbindung kann
denselben Namen wie eine globale Variable haben
Das Programm ist in diesem Fall schlecht geformt.
(keine Diagnose erforderlich, wenn sie
in verschiedenen Übersetzungseinheiten vorkommen)
CWG 564 C++98 Das Programm war schlecht formuliert, wenn zwei Deklarationen
sich nur in den Sprachbindungsspezifikationen unterscheiden
(d. h. unterschiedliche String-Literale nach 'extern')
Die tatsächlichen Sprachbindungen, die von
den Deklarationen gegeben werden, werden stattdessen verglichen
CWG 2460 C++20 friend-Funktionen mit einer nachfolgenden requires Klausel
und "C"-Sprachbindung hatten widersprüchliche Verhaltensweisen
"C"-Sprachbindung
wird in diesem Fall ignoriert
CWG 2483 C++98 Die Bindung der Typen von statischen Member-Funktionen
die in "C"-Sprachblöcken erscheinen, war "C++"
Die Bindung ist "C"

[bearbeiten] Referenzen

  • C++23 Standard (ISO/IEC 14882:2024)
  • 9.11 Linkage specifications [dcl.link]
  • C++20 Standard (ISO/IEC 14882:2020)
  • 9.11 Linkage specifications [dcl.link]
  • C++17 Standard (ISO/IEC 14882:2017)
  • 10.5 Linkage specifications [dcl.link]
  • C++14 Standard (ISO/IEC 14882:2014)
  • 7.5 Linkage specifications [dcl.link]
  • C++11 Standard (ISO/IEC 14882:2011)
  • 7.5 Linkage specifications [dcl.link]
  • C++03-Standard (ISO/IEC 14882:2003)
  • 7.5 Linkage specifications [dcl.link]
  • C++98 Standard (ISO/IEC 14882:1998)
  • 7.5 Linkage specifications [dcl.link]