Hallo, ich habe eine h Datei mit einem Compilerswitch. Diese h Datei inkludiere ich in Cpp files. In einem Cpp file (a.cpp) setze ich den Compilerswitch. Darin ist nach meinem Verständnis dann die variable var definiert. In einem anderen Cpp file (b.cpp) inkludiere ich auch diese h Datei allerdings ohne setzen des Compilerswitches. var ist ja bereits definiert und ich möchte sie woanders lesen. Aus der h Datei : #if defined(switchA) int var = 9; #else extern int var; #endif : Im jeweiligen cpp file kann ich lesend auf var zugreifen. Ihr Wert ist in beiden Fällen 9. Setze ich nun const ein, bekomme ich folgende Fehlermeldung: "undefinde reference to var." Zum einen verstehe ich nicht warum ich die Fehlermeldung bekomme und was müsste ich tun, damit Aus der h Datei : #if defined(switchA) const int var = 9; #else extern const int var; #endif :
const-qualified (non-volatile) variables which are not declared extern have internal linkage. Lösung: In der header-Datei:
1 | const int var = 9; |
Besser: In der header-Datei:
1 | constexpr int var = 9; |
Oliver
Sven schrieb: > Aus der h Datei > : > #if defined(switchA) > int var = 9; > #else > extern int var; > #endif > : Warum machst du sowas? Die Definition der Variablen hat im Header nichts zu suchen. > Setze ich nun const ein, bekomme ich folgende Fehlermeldung: > > "undefinde reference to var." In C++ haben Konstanten "internal linkage". Man kann also nicht per extern darauf zugreifen.
Oliver S. schrieb: > const-qualified (non-volatile) variables which are not declared extern > have internal linkage. > > Lösung: > In der header-Datei: >
1 | const int var = 9; |
> > Besser: > In der header-Datei: >
1 | constexpr int var = 9; |
> > Oliver Besser:
1 | inline constexpr int var = 9; |
Rolf M. schrieb: > In C++ haben Konstanten "internal linkage". Man kann also nicht per > extern darauf zugreifen. Eine Frage, die mir durch den Kopf geht: Hat der "const int" in allen Sources, die den Header einbinden, die selbe Addresse? "internal linkage" klingt erst einmal nicht so.
Danke und sorry, hat mir alles leider irgendwie nicht weitergeholfen. Erster Code snippet funktioniert. Hier kann ich schreibend und lesend auf var in den cpp Dateien zugreifen. Zweiter Code snippet funktioniert nicht. Hier will ich nur lesend zugreifen mit const zulassen. Ja, ich weiß, die var Definition kann ich auch in eine cpp Datei packen. Ich frage aber nach der Möglichkeit dies in einer h Datei zu machen. Rolf M. schrieb: > In C++ haben Konstanten "internal linkage". Man kann also nicht per > extern darauf zugreifen. Bedeutet es gibt in dem Header Ansatz keine Möglichkeit. extern und const geht nicht. Warum da schreiben und lesen geht aber nur lesen nicht, ist zumindest für den nicht Vollprofi schwer zu verstehen.
1 | :
|
2 | #if defined(switchA)
|
3 | int var = 9; |
4 | #else
|
5 | extern int var; |
6 | #endif
|
7 | :
|
1 | :
|
2 | #if defined(switchA)
|
3 | const int var = 9; |
4 | #else
|
5 | extern const int var; |
6 | #endif
|
7 | :
|
Sven schrieb: > Bedeutet es gibt in dem Header Ansatz keine Möglichkeit. > extern und const geht nicht. Geht schon.
1 | #if defined(switchA)
|
2 | extern const int var = 9; |
3 | #else
|
4 | extern const int var; |
5 | #endif
|
Wie aber schon geschrieben wurde, mach das nicht (für POD-Datentypen). Dafür gibt es constexpr. Oliver
Die Variablen Definition gehört in eine cpp Datei. test.h
1 | #pragma once
|
2 | extern const int var; |
test.cpp
1 | #include test.h
|
2 | const int var = 6; |
Rolf M. schrieb: > In C++ haben Konstanten "internal linkage". Man kann also nicht per > extern darauf zugreifen. Gut das mein Compiler das nicht weiß! Denn der tut das avr-gcc-11.1.0-x64-windows -std=gnu++17 Vincent H. schrieb: > Besser:inline constexpr int var = 9; Warum nicht sofort static inline constexpr int var {9}; Ob static oder/und inline, oder keins von beiden, bleibt sich gleich
EAF schrieb: > Gut das mein Compiler das nicht weiß! > Denn der tut das Der weiß das, und tut das genauso wenig wie beim TO. Du hast das Problem nicht ganz verstanden. Oliver
Oliver S. schrieb: > Du hast das Problem > nicht ganz verstanden. Dann sage mir doch bitte wo mein Denkfehler ist.
EAF schrieb: > Ob static oder/und inline, oder keins von beiden, bleibt sich gleich Nein, ohne inline steht es dem Compiler frei für jede Source Datei eine Kopie von var anzulegen. Das mag bei einem int noch egal sein, aber wenn es sich um zig-kB große Arrays handeln würde wär das für Mikrocontroller wohl nicht so wünschensweert.
EAF schrieb: > Dann sage mir doch bitte wo mein Denkfehler ist. Du brauchst nur den Ausgangsbeitrag richtig zu lesen. Hinweis: Zähl mal, um wieviele Dateien es da geht (und warum es die defines überhaupt brauchen könnte). Oliver
Vincent H. schrieb: > Nein, ohne inline steht es dem Compiler frei für jede Source Datei eine > Kopie von var anzulegen. Das mag bei einem int noch egal sein, aber wenn > es sich um zig-kB große Arrays handeln würde wär das für Mikrocontroller > wohl nicht so wünschensweert. Allerdings sind die Compiler und Linker ziemlich gut darin, constexpr-Variable ganz zu eliminieren. Oliver
EAF schrieb: > Rolf M. schrieb: >> In C++ haben Konstanten "internal linkage". Man kann also nicht per >> extern darauf zugreifen. > Gut das mein Compiler das nicht weiß! > Denn der tut das > avr-gcc-11.1.0-x64-windows -std=gnu++17 Dann ist er wohl irgendwie kaputt. Bei meinem kommt jedenfalls wie zu erwarten eine "undefined reference to `var'".
Tja, könnte bitte jemand hier ein code snippet reinkopieren von dem er weiß, das es funktionieren tut? Definition in einer h Datei mit Compilerswitch. Die Variante mit Aufteilung in cpp und hpp bekomme ich hin. Es wurde ja viel geschrieben aber pragmatisch geholfen leider noch nicht. Google habe ich auch schon bemüht. Ich kann nur sagen, das funktioniert bei mir nicht
1 | :
|
2 | #if defined(switchA)
|
3 | const int var = 9; |
4 | #else
|
5 | extern const int var; |
6 | #endif
|
7 | :
|
und alle Abwandlungen mit extern, constexpr, inline und Kombinationen funktionieren auch nicht. Das funktioniert:
1 | :
|
2 | #if defined(switchA)
|
3 | int var = 9; |
4 | #else
|
5 | extern int var; |
6 | #endif
|
7 | :
|
Sven schrieb: > Tja, > könnte bitte jemand hier ein code snippet reinkopieren von dem er weiß, > das es funktionieren tut? Definition in einer h Datei mit > Compilerswitch. Oliver S. schrieb: >
1 | > #if defined(switchA) |
2 | > extern const int var = 9; |
3 | > #else |
4 | > extern const int var; |
5 | > #endif |
6 | >
|
> > Wie aber schon geschrieben wurde, mach das nicht (für POD-Datentypen). > Dafür gibt es constexpr. Oliver
Hallo Oliver, Das funktioniert! Ich hatte obiges extern übersehen. Frage mich auch ein wenig, wieso das da sein muss. Das untere extern wäre mir klar.
1 | :
|
2 | #if defined(switchA)
|
3 | extern const int var = 9; |
4 | #else
|
5 | extern const int var; |
6 | #endif
|
7 | :
|
Was auch funktioniert: Soweit ich nachgelesen habe sagt constexpr aus das es sich hier um eine Variable handelt, die explizit zur Compilezeit bekannt ist. Sie muss da wohl auch initialisiert sein sonst zeigt das der Compiler an. Der zweite Teil mit
1 | extern const int var; |
Wird somit wohl nur so funktionieren und kann nicht mit constexpr funktionieren? Oder?
1 | :
|
2 | #if defined(switchA)
|
3 | extern constexp int var = 9; |
4 | #else
|
5 | extern const int var; |
6 | #endif
|
7 | :
|
Sven schrieb: > Wird somit wohl nur so funktionieren und > kann nicht mit constexpr funktionieren? Oder? Mit constexpr brauchst du kein extern. Du schreibst in deinen Header einfach:
1 | constexpr int var = 9; |
und sonst nichts. Kein Compiler-Switch, kein extern.
Rolf M. schrieb: > und sonst nicht. außer dem auch schon hier ausführlich diskutierten static oder inline davor. Oliver
OK und mit dem
1 | constexpr int var = 9; |
im Header ist sichergestellt, dass diese Variable nur einmal angelegt wird? Sie soll nur einmal angelegt werden und nicht in jeder cpp Übersetzungseinheit.
Idealerweise wird sie garnicht angelegt, es sei denn du machst Kapriolen wie die Adresse von var zu nehmen.
Im www habe es nun so verstanden das in C++17 diese
1 | inline constexpr int var = 9; |
Definition in einem Header sein kann und dieser Header kann in x beliebigen cpp Dateien inkludiert sein. Es wird nur einmal angelegt. Ob da nun inline davor muss oder der Compiler da was macht weiss ich net. So wie oben wäre es aber wohl nicht verkehrt.
Sven schrieb: > Es wird nur einmal angelegt. Es wird maximal einmal angelegt. Wie schon mehrfach angedeutet wurde, wird (bei eingeschalteter Optimierung) der Compiler die letztendlich gar nicht anlegen, sondern überall direkt den Wert einsetzen. Oliver
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.