Warum ist die Mehrfachdefinition einer konstanten globalen Variablen in C++ erlaubt und nicht in C?

Lesezeit: 5 Minuten

Benutzer-Avatar
Ashwin Nanjappa

Die Mehrfachdefinition einer globalen Variablen ist in C oder C++ aufgrund der One-Definition-Rule nicht erlaubt. In C++ kann jedoch eine konstante globale Variable ohne Fehler in mehreren Kompilierungseinheiten definiert werden. Das ist nicht dasselbe wie in C.

Warum erlaubt C++ dies, während C dies nicht tut? Warum unterscheidet sich die Verwendung und das Verhalten eines konstanten Globals in C++ auf diese Weise von einem nicht konstanten Global im Vergleich zu C? Was passiert unter der Decke mit C++ und C in Bezug auf const?

Zum Beispiel ist dies in C++ erlaubt, aber in C falsch:

// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;
int main()
{
    cout << Foo << endl;
    return 0;
}

Und das ist in C in Ordnung, aber in C++ falsch:

// Foo.cpp
const int Foo = 99;

// Main.cpp
extern const int Foo;
int main()
{
    cout << Foo << endl;
    return 0;
}

  • Du scheinst deine Frage selbst beantwortet zu haben…? Über welchen Teil sind Sie verwirrt?

    – Merlyn Morgan-Graham

    30. Mai 2011 um 8:21 Uhr


  • Ich vermute, er ist verwirrt darüber, dass er eine Konstante int nicht als extern deklarieren kann, ohne Verknüpfungsfehler zu erhalten.

    – Iolo

    30. Mai 2011 um 8:23 Uhr

  • Merlyn: Ich weiß, wie man const in C++ verwendet. Mich interessiert, warum const so entworfen wurde und nicht wie eine normale globale Variable?

    – Ashwin Nanjappa

    30. Mai 2011 um 8:24 Uhr

  • Dies ist wohl ein Duplikat von stackoverflow.com/questions/998425/…

    – MSalter

    30. Mai 2011 um 8:58 Uhr

Benutzer-Avatar
Nawaz

// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;

const Variable im Namespace-Bereich hat intern Verknüpfung. Sie sind also im Grunde zwei verschiedene Variablen. Es gibt keine Neudefinition.

Aus @ Davids Kommentar, 3,5/3 [basic.link]:

Ein Name mit Namensraumbereich (3.3.5) hat interne Verknüpfung wenn es der Name ist
— ein Objekt, eine Referenz, eine Funktion oder eine Funktionsvorlage, die explizit als statisch deklariert ist, oder
— ein Objekt oder eine Referenz, das ist ausdrücklich als const deklariert und weder explizit als extern deklariert noch zuvor als externe Verknüpfung deklariert; oder
— ein Datenmitglied einer anonymen Vereinigung.


Im zweiten Fall sollten Sie dies tun (richtiger Weg):

//Foo.h
extern const int Foo; //use extern here to make it have external linkage!

// Foo.cpp
#include "Foo.h"
const int Foo = 99; //actual definition goes here

// Main.cpp
#include "Foo.h"
int main()
{
   cout << Foo << endl;
}

  • Danke Nawaz. Wird dies irgendwo im Buch zur Programmiersprache C++ oder in einer anderen Referenz erklärt?

    – Ashwin Nanjappa

    30. Mai 2011 um 8:22 Uhr

  • Im Standard… 3,5/3 [basic.link]: Ein Name mit Namespace-Geltungsbereich (3.3.5) hat eine interne Verknüpfung, wenn es sich um den Namen handelt von – einem Objekt, einer Referenz, einer Funktion oder einer Funktionsvorlage, die ausdrücklich als statisch deklariert ist, oder – ein Objekt oder eine Referenz, die explizit als const deklariert und weder explizit als extern deklariert noch zuvor als externe Verknüpfung deklariert wurde; oder — ein Datenmitglied einer anonymen Vereinigung.

    – David Rodríguez – Dribeas

    30. Mai 2011 um 8:26 Uhr


  • @David: Ich habe deinen Kommentar in meinem Beitrag zitiert. Ich habe nach der Anfrage von @Ashwin im Standard nach diesem Text gesucht, aber Sie haben mir die Arbeit leicht gemacht. Hoffe es stört dich nicht.

    – Nawaz

    30. Mai 2011 um 8:30 Uhr


  • Ich denke, sollte enthalten Foo.h in Foo.cpp auch sonst Foo ist nicht mit externer Verlinkung deklariert.

    – Matthias M.

    30. Mai 2011 um 8:46 Uhr

  • @Matthieu: Stimmt. Ich habe nur vergessen, das zu tun. Vielen Dank 🙂

    – Nawaz

    30. Mai 2011 um 8:49 Uhr

Ich denke, Sie fragen nach der Begründung und nicht nach der spezifischen Sprachregel, die dies zulässt.

Die Begründung dafür ist, dass es macht const Variablen viel einfacher zu verwenden. Es gibt einen typisierten Ersatz für eine häufige Verwendung von #define.

Anstatt von #define MAX_COUNT 211 Sie können verwenden const int max_count = 211; auf genau die gleiche Weise, zB eine gemeinsam genutzte Header-Datei, ohne sich Gedanken darüber machen zu müssen, wo die eine Definition abgelegt werden soll.

Sie können den Wert von a nicht legal ändern const Objekt, sodass es keinen sichtbaren Unterschied zwischen einem Objekt und mehreren Objekten mit demselben Wert gibt.

Wie Sie eine Definition von a setzen können const -Objekt in einer Header-Datei macht es für den Compiler trivial, den Wert direkt in der Kompilierungsphase zu verwenden, ohne dass solche Optimierungen auf eine Korrektur zur Verbindungszeit verzögert werden müssen.

  • Können Sie auch erklären, warum sich dieses C++-Verhalten von const von C unterscheidet? Der obige Code, der in C++ funktioniert, hat einen Mehrfachdefinitionsfehler in C!

    – Ashwin Nanjappa

    30. Mai 2011 um 8:40 Uhr

  • @Ashwin: Ich fürchte nicht. Ich glaube, dass C mehr Abwärtskompatibilitätsprobleme hatte (unterstützende vorläufige Definitionen?) und am Ende eine kompromittiertere Version hatte const aber ich habe keine direkten Beweise dafür.

    – CB Bailey

    30. Mai 2011 um 8:43 Uhr

  • @AshwinNanjappa Ich nehme an, C zieht es in diesem Fall einfach vor, die Verwendung von Schlüsselwörtern konsistent zu halten – wenn Sie static angeben, erhalten Sie eine interne Verknüpfung. Andernfalls erhalten Sie eine externe Verlinkung 🙂

    – Martinkunew

    16. November 2015 um 14:13 Uhr

Grundsätzlich sind in C++ const, nicht lokale Variablen echte konstante Ausdrücke oder constexpr. Dies erlaubt viele Dinge, wie TMP.

const int five = 5;
int main() {
    int x[five];
    std::array<int, five> arr;
}

In C sind sie nur eine Variable, die nicht geändert werden kann. Das ist,

const int five = 5;
int main() {
    int x[five]; // Technically, this is a variable length array
}

Ist durchaus gleichwertig

int five = 5;
int main() {
    int x[five];
}

Tatsächlich fördert C++ einige Arten von const Variable in eine neue Kategorie, constexprwährend dies in C nicht existiert und es sich nur um Variablen handelt, die zufällig nicht änderbar sind.

Benutzer-Avatar
Alex B

Es sieht aus wie konst erzeugt nicht wirklich ein externes Symbol.

Warum schreiben Engländer COLOUR, während Amerikaner es COLOR buchstabieren?

Es sind 2 verschiedene Sprachen von der gleichen Basis, aber sie haben nicht die gleichen Regeln.

C und C++ sind gleich. Wenn sie nicht verschieden wären, würden sie beide gleich heißen.

  • “Warum sind sie anders?” “Weil sie nicht gleich sind!” Nicht nützlich.

    – josaphatv

    20. Mai 2015 um 20:59 Uhr

Benutzer-Avatar
hkf

Meine Problemumgehung deklarierte es als:

static classfoo foo;

es hat in meiner Situation funktioniert.

  • “Warum sind sie anders?” “Weil sie nicht gleich sind!” Nicht nützlich.

    – josaphatv

    20. Mai 2015 um 20:59 Uhr

1367850cookie-checkWarum ist die Mehrfachdefinition einer konstanten globalen Variablen in C++ erlaubt und nicht in C?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy