Konstante in separater Datei



  • Da diese Frage immer wieder falsch beantwortet wird: Linkerfehler haben in erster Linie nichts mit Include-Guards zu tun!

    Das Problem ist, dass die Variable mehrfach definiert wird. In den Header gehört eine Deklaration:

    extern const char* const X; // das 2. const macht den Zeiger erst konstant
    

    In einer Implementierungsdatei muss die Definition stehen:

    extern const char* const X = "hallo";
    

    Bei Konstanten könnte man auch interne Bindung nutzen (indem man keine Speicherklasse angibt), aber dann wird die Variable für jedes Modul einzeln erstellt. Das gleiche Verhalten erreicht man mit der Speicherklasse static .

    Übrigens sollte man stets versuchen, globale Variablen zu vermeiden.



  • Warum funktioniert aber eine Konstantendefinition für einfache Datentypen wie const int auch mit Zuweisung?



  • Ok, danke Nexus, hätte aber noch 2 Fragen:

    1. Warum gibt er mir bei static keinen Fehler? Also wenn ich in der Header Datei
    static const char* X = "Hallo";
    

    schreibe?

    1. Für was steht denn in
    const char* const X
    

    das erste const?



  • ichben schrieb:

    Warum funktioniert aber eine Konstantendefinition für einfache Datentypen wie const int auch mit Zuweisung?

    Wie angetönt: Weil const -qualifizierte globale Variablen standardmässig (d.h. ohne explizite Angabe einer Speicherklasse) intern gelinkt werden.



  • Variablen, die static sind, existieren nur in dieser Übersetzungseinheit und sind von anderen ÜE aus nicht erreichbar, dafür kannst du den gleichen Namen auch in anderen ÜE verwenden.
    Das bedeutet zwar, dass die Variable in jeder ÜE einmal existiert, aber die meisten Linker führen z.B. gleiche Stringkonstanten zusammen, so dass sie nur einmal im Binary auftauchen.

    Don Quijote schrieb:

    1. Für was steht denn in
    const char* const X
    

    das erste const?

    Das erste const bezieht sich auf das char - d.h. es handelt sich um einen Zeiger auf ein konstantes char. Erst das zweite const macht auch den Zeiger selbst konstant.



  • Don Quijote schrieb:

    1. Warum gibt er mir bei static keinen Fehler? Also wenn ich in der Header Datei
    static const char* X = "Hallo";
    

    schreibe?

    Weil du durch das static explizit eine nicht-konstante Variable mit interner Linkage versiehst. Der Linker erstellt eine unabhängige Variable pro Modul.

    Don Quijote schrieb:

    1. Für was steht denn in
    const char* const X
    

    das erste const?

    Das bezieht sich auf das char , auf das der Zeiger verweist (und nicht etwa auf den Zeiger selbst). Wenn du X dereferenzierst, erhältst du Zugriff auf const char , d.h. du kannst die Zeichen nicht verändern. Das ist bei Stringliteralen wie "Hallo" auch sinnvoll.



  • Na klar, macht Sinn,

    Vielen Dank an alle Beteiligten.

    btw.: Das hier hab ich noch nie in irgendeinem Tutorial gelesen.



  • Athar schrieb:

    Variablen, die static sind, existieren nur in dieser Übersetzungseinheit und sind von anderen ÜE aus nicht erreichbar, dafür kannst du den gleichen Namen auch in anderen ÜE verwenden.

    Ja. static in Headern ist aber eher ungewöhnlich. Das Problem ist eher relevant, wenn man in einer Implementierungsdatei ein globales Symbol erstellt, welches sich mit Bezeichnern in anderen Modulen überschneiden könnte. Dann empfehlen sich übrigens anonyme Namensräume.

    Athar schrieb:

    Das bedeutet zwar, dass die Variable in jeder ÜE einmal existiert, aber die meisten Linker führen z.B. gleiche Stringkonstanten zusammen, so dass sie nur einmal im Binary auftauchen.

    Du musst hier vorsichtig sein, dass du nicht zwei Dinge vermischst: Stringliterale, welche das Programm im statischen Speicherbereich hält, und globale Variablen (hier Zeiger, die auf Stringliterale verweisen). Die Speicherklasse von Variablen kann der Programmierer beeinflussen, die von Stringliteralen nicht.

    Don Quijote schrieb:

    btw.: Das hier hab ich noch nie in irgendeinem Tutorial gelesen.

    Sinnvoller wäre es auch, du würdest ein Buch lesen. Du wirst noch einiges von C++ nicht mitkriegen, wenn du dein Wissen aus Internettutorials zusammensammelst. Oft empfohlen werden z.B. der C++ Primer oder Thinking in C++ (auch gratis als Online-PDF erhältlich).



  • Ok, hab mich vlt. falsch ausgedrückt, ich habe bereits ein Buch gelesen, allerdings eher für Anfänger. Trotzdem danke für den Tipp.



  • Nexus schrieb:

    Du musst hier vorsichtig sein, dass du nicht zwei Dinge vermischst: Stringliterale, welche das Programm im statischen Speicherbereich hält, und globale Variablen (hier Zeiger, die auf Stringliterale verweisen). Die Speicherklasse von Variablen kann der Programmierer beeinflussen, die von Stringliteralen nicht.

    Aber auch hier gilt, dass kein physischer Speicher für die Variablen bereitgestellt werden muss, sofern deren Adresse nicht angefordert wird.
    Letztendlich wollte ich darauf hinaus, dass static nicht unbedingt die Binarygröße erhöhen muss.


Anmelden zum Antworten