Ich schon wieder.
Wenn ich ein Programm in mehrere .c-Files aufgespalten und globale
Variablen deklariert habe, auf die mehrere Dateien zugreifen müssen,
habe ich bis jetzt immer eine globals.h geschrieben, die dann in allen
Files eingebunden wird. Bin aber grade ins Grübeln gekommen: Ist das die
sinnvollste Möglichkeit?
TechInfo wrote:
> Ich schon wieder.>> Wenn ich ein Programm in mehrere .c-Files aufgespalten und globale> Variablen deklariert habe, auf die mehrere Dateien zugreifen müssen,> habe ich bis jetzt immer eine globals.h geschrieben, die dann in allen> Files eingebunden wird. Bin aber grade ins Grübeln gekommen: Ist das die> sinnvollste Möglichkeit?
Ja.
Die Alternative ist, die globalen in ihrer jeweilgen
*.c zu definieren
1
intGlobaleVar1;
2
intGlobaleVar2;
3
4
voidfoo()
5
{
6
GlobaleVar1=5;
7
GlobaleVar2=8;
8
}
und in allen anderen *.c nur diejenigen Globalen Variablen
zu deklarieren, die tatsächlich gebraucht werden:
1
externintGlobaleVar2;
2
3
voidbar()
4
{
5
GlobaleVar2=9;
6
}
auf lange Sicht zeigt sich aber, dass sowas in Chaos ausartet.
Alle Globalen in einem Header sammeln, ...
globale.h
*********
1
#ifndef EXTERN
2
#define EXTERN extern
3
#endif
4
5
EXTERNintGlobaleVar1;
6
EXTERNintGlobaleVar2;
... und die dann includieren ...
main.c
******
1
//
2
// durch den #define expandiert das Makro EXTERN in globale.h zu
3
// einem Leerstring. Dadurch wird aus
4
// EXTERN int a;
5
// die Zeile
6
// int a;
7
// und das definiert die Variable a
8
//
9
#define EXTERN
10
#include"globale.h"
11
12
intmain()
13
{
14
}
a.c
***
1
//
2
// Hier gibt es keinen #define
3
// Dadurch definiert sich globale.h selbst ein Makro für EXTERN
4
// welches EXTERN durch 'extern' ersetzt. Aus
5
// EXTERN int a;
6
// wird daher
7
// extern int a;
8
// und das deklariert die Variable a ohne sie zu definieren
9
//
10
#include"globale.h"
11
12
voidfoo()
13
{
14
GlobaleVar1=5;
15
GlobaleVar2=8;
16
}
b.c
***
1
#include"globale.h"
2
3
voidbar()
4
{
5
GlobaleVar2=9;
6
}
ist auf lange Sicht die deutlich wartungsfreundlichere Lösung.
Dabei kann es durchaus sein, dass man für globale Variablen
mehrere Header Files macht, in denen die Globalen nach Themenkreisen
aufgeteilt sind. Das Prinzip ist aber dasselbe.
Braucht es denn diesen Makro unbedingt?
Kann man nicht in die Header-Datei
extern int GlobaleVariable
schreiben, die Header-Datei dann in jede .c einbinden und in einer
.c-Datei dann noch zusätzlich die Definition
int GlobaleVariable
schreiben?
Oder beißen sich dann die Deklaration aus der Header-Datei und dei
Definition aus der .c?
Aber hier Beitrag "Problem mit globaler Variable" schreibst du, dass
er in die Header-Datei die Variable mit extern deklarieren soll, und
dann in einer .c die Variable definieren. Da die Header-Datei aber in
beide files eingebunden wird, müßte es sich da doch auch beißen, oder?
TechInfo wrote:
> Braucht es denn diesen Makro unbedingt?
Brauchen tut man das EXTERN Makro nicht unbedingt.
>> Kann man nicht in die Header-Datei>> extern int GlobaleVariable>> schreiben, die Header-Datei dann in jede .c einbinden und in einer> .c-Datei dann noch zusätzlich die Definition>> int GlobaleVariable>> schreiben?
Sicher kannst du.
Nur tippst du dann jede Variable 2 mal:
Einmal wenn du sie ins Header File einfügst. Das zweite
mal, wenn du sie dann in das eine bewusste *.c File
einfügst. Es soll schon vorgekommen sein, dass man beim
Tippen von ein und demselben Variablennamen Tippfehler
macht :-)
>> Oder beißen sich dann die Deklaration aus der Header-Datei und dei> Definition aus der .c?
Nein.
Im Endeffekt macht ja das Makro auch nichts anderes.
Mit dem EXTERN hab ich einfach nur einen Mechanismus, dass
ich beim includen in viele Files ein 'extern' davor kriege
und nur bei einem einzigen File wird das 'extern' unterdrückt.
Ist doch (fast) perfekt.
Fast perfekt deshalb, weil das ganze bei Initialisierungen
nicht mehr greift:
Ist bei einer Variablendekleration
extern int i = 0;
eine Initialisierung angegeben, dann wird das extern leider
ignoriert. Andersrum wärs mir lieber, ist aber so.
> Oder beißen sich dann die Deklaration aus der Header-Datei und dei> Definition aus der .c?
Um das nochmal aufzugreifen:
Du kannst von einem Ding beliebig viele Deklerationen haben,
solange die Deklerationen immer das gleiche aussagen.
1
externinti;
2
externinti;
ist perfektes C.
Sieh es so: Eine derartige Dekleration kann umgangssprachlich
gelesen werden als:
Es gibt irgendwo eine Variable i. Wo es die gibt, braucht dich
jetzt nicht zu kümmern. Nimm einfach zur Kenntnis, dass sie
da ist und das daher in weiterer Folge die Verwendung von i
kein Syntaxfehler ist. Ach ja. Die Variable i ist vom Typ int.
Wenn der Compiler zum ersten mal auf diese Dekleration stöst,
dann trägt er in seine internen Tabellen ein: i existier, ist
vom Typ int.
Wenn der Compiler zum zweiten mal auf diese Dekleration stöst,
dann merkt er aufgrund seiner internen Tabellen: "Weis ich schon"
und macht nichts.
Wenn du schreibst
1
externinti;
2
externinti;
3
inti;
dann läuft bei den ersten beiden Deklerationen genau dasselbe
ab. Dann kommt die Definition und der Compiler wird zusätzlich
auch noch angehalten diese Variable jetzt auch tatsächlich
zu erzeugen. Da aber die Deklerationen und die Definitionen
übereinstimmen (in allen Fällen lautet die Aussage: ist vom Typ int)
hat der Compiler keinen Grund, da rumzumäkeln.
>> Oder beißen sich dann die Deklaration aus der Header-Datei und dei>> Definition aus der .c?>>Nein.>Im Endeffekt macht ja das Makro auch nichts anderes.>Mit dem EXTERN hab ich einfach nur einen Mechanismus, dass>ich beim includen in viele Files ein 'extern' davor kriege>und nur bei einem einzigen File wird das 'extern' unterdrückt.>Ist doch (fast) perfekt.
Das Makro macht schon etwas anderes. Ohne das Makro wird in EINER
.c-Datei, nämlich in der wo die Variable definiert wird, nach Auflösung
der include-Anweisung stehen:
extern int var;
int var;
Durch das Makro wird in besagter Datei dann nur stehen:
int var;
TechInfo wrote:
> Das Makro macht schon etwas anderes. Ohne das Makro wird in EINER> .c-Datei, nämlich in der wo die Variable definiert wird, nach Auflösung> der include-Anweisung stehen:>> extern int var;> int var;>> Durch das Makro wird in besagter Datei dann nur stehen:>> int var;
Das macht aber logisch gesehen keinen Unterschied.
Gerade kürzlich hatte ich mit 'nem Compiler zu tun, der tatsächlich
motzte, wenn eine Variable sowohl extern als auch nicht-extern
deklariert wurde - aber das scheint glücklicherweise die Ausnahme zu
sein. Naja, MS halt.
Hi
Sehr gut, wie ihr das hier mit extern erklärt habt. Klingt auch alles
sehr logisch. Nur ich mache das immer ohne "extern" und es funzt auch.
Soll heißen: Die Headerdatei mit der Definition z.B.
volatile uint8_t var;
wird in jede Datei eingebunden, in der die Variable var benötigt wird.
Und das klappt.
Ist das aus irgendwelchen Günden schlecht? Oder passiert da sogar
irgendwas, was ich zwar nicht bemerke, was mir aber trotzdem Probleme
bereiten könnte?
VG
felix
Felix wrote:
> Hi>> Sehr gut, wie ihr das hier mit extern erklärt habt. Klingt auch alles> sehr logisch. Nur ich mache das immer ohne "extern" und es funzt auch.> Soll heißen: Die Headerdatei mit der Definition z.B.>> volatile uint8_t var;>> wird in jede Datei eingebunden, in der die Variable var benötigt wird.> Und das klappt.
Das klappt weil dein Compiler/Linker eine Erweiterung mit
haben, die eine derartige 'multiple definition' unterstützt.
Wenn man pingelig ist, könnte man sagen du programmierst in
irgendeiner Sprache, die zwar fast wie C aussieht aber nicht
C sein kann. Denn in C ist sowas verboten :-)
PS: Der gcc kann das auch. Trotzdem mache ich das nicht. Das
extern kostet mir nichts und ich bin zumindest an dieser Stelle
C-konform.
Karl heinz Buchegger wrote:
> Sicher kannst du.> Nur tippst du dann jede Variable 2 mal:> Einmal wenn du sie ins Header File einfügst. Das zweite> mal, wenn du sie dann in das eine bewusste *.c File> einfügst.
Dann denkt man aber einmal mehr drüber nach, ob man wirklich eine
externe Variable braucht. ;-)
> Es soll schon vorgekommen sein, dass man beim> Tippen von ein und demselben Variablennamen Tippfehler> macht :-)
Dafür können Editoren aber seit 20 Jahren copy&paste, nicht?
> Wenn man pingelig ist, könnte man sagen du programmierst in> irgendeiner Sprache, die zwar fast wie C aussieht aber nicht> C sein kann. Denn in C ist sowas verboten :-)
Bist du dir da so sicher? Das Überlagern gleichnamiger externer
Variablen in einem common block ist eine der ,,historisch
gewachsenen'' Implementierungsmöglichkeiten, die im Standard zumindest
irgendwo erwähnt war...
Ah nein, hab's gefunden. Nicht im Standard, sondern im C99 Rationale,
Punkt 6.2.2. ``Linkages of identifiers''. Dort werden Programme, die
nach sich auf dieses Prinzip (Relaxed Ref/Def) verlassen beschrieben
als:
`` ... UNIX C programs which take advantage of this model are standard
conforming in their environment, but are not maximally portable (not
strictly conforming).''