Forum: Mikrocontroller und Digitale Elektronik extern const


von Sven (Gast)


Lesenswert?

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
:

von Oliver S. (oliverso)


Lesenswert?

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

von Rolf M. (rmagnus)


Lesenswert?

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.

von Vincent H. (vinci)


Lesenswert?

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;

von Heiko L. (zer0)


Lesenswert?

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.

von Sven (Gast)


Lesenswert?

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
:

von Oliver S. (oliverso)


Lesenswert?

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

von EAF (Gast)


Lesenswert?

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

von Oliver S. (oliverso)


Lesenswert?

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

von EAF (Gast)


Lesenswert?

Oliver S. schrieb:
> Du hast das Problem
> nicht ganz verstanden.
Dann sage mir doch bitte wo mein Denkfehler ist.

von Vincent H. (vinci)


Lesenswert?

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.

von Oliver S. (oliverso)


Lesenswert?

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

von Oliver S. (oliverso)


Lesenswert?

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

von Rolf M. (rmagnus)


Lesenswert?

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'".

von Sven (Gast)


Lesenswert?

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
:

von Oliver S. (oliverso)


Lesenswert?

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

von Sven (Gast)


Lesenswert?

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
:

von Rolf M. (rmagnus)


Lesenswert?

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.

von Oliver S. (oliverso)


Lesenswert?

Rolf M. schrieb:
> und sonst nicht.

außer dem auch schon hier ausführlich diskutierten static oder inline 
davor.

Oliver

von Sven (Gast)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Idealerweise wird sie garnicht angelegt, es sei denn du machst Kapriolen 
wie die Adresse von var zu nehmen.

von Sven (Gast)


Lesenswert?

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.

von Oliver S. (oliverso)


Lesenswert?

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
Noch kein Account? Hier anmelden.