Forum: Compiler & IDEs mehrere c-files auf eine .h zugreifen


von microchip (Gast)


Lesenswert?

hi leute!

Ich habe mehrere .c datein, welche auf eine .h datei zugreifen sollen 
(#include)

Ich bekomme aber leider jedes mal einen "Build Failed".

Ich will aber nicht die variablen 2 mal deklarieren (einmal normal, und 
dann nochmal als extern!)


Hier ein bsp!

main.c:
1
#include "main.h"
2
3
main(void)
4
{
5
test(a);
6
tesst(b);
7
}


teil.c:
1
#include "main.h"
2
3
test(char aaa)
4
{
5
a++;
6
b=aaa;
7
}

anderer.c:
1
#include "main.h"
2
tesst(char bbbb)
3
{
4
b++;
5
a=bbbb;
6
}

main.h
1
#ifndef _main_h
2
#define _main_h
3
char a,b;
4
#endif


Ich weiss, dass ich bei teil.c & anderer.c die main.h datei entfernen 
muesste, und dafuer ein extern char a,b schreiben muesste. Aber diese 
abtipselei will ich mir sparen.

Gibt es hier irgendeinen trick?

: Verschoben durch User
von gast (Gast)


Lesenswert?

bei globalen variablen wirst du da wohl nicht drumrum kommen...

gut man kann etwas machen wie:


main.h:

#ifndef _main_h
#define _main_h

#ifdef ISMAIN
  #define blubb
#else
  #define blubb extern
#endif

blubb char a,b;
#endif


------
main.c

#define ISMAIN
#include "main.h"

dann wird eben nur die variable im main source deklariert ansonsten als 
extern...

ob das jetzt toll ist... ist ne andere frage ;)

von ozo (Gast)


Lesenswert?

Also "normal" wäre das so:

deklaration der variablen in main.h:
extern int blupp;

definition der varibalen in main.c:
int blupp;

anderes_file.c:
#include main.h

blupp = 172635;

von der mechatroniker (Gast)


Lesenswert?

Nicht vergessen:

#include "main.h"

auch in main.c (Dann kann der Compiler meckern, wenn die Typen nicht 
übereinstimmen).

von Bertram S. (bschall)


Lesenswert?

main.c
1
    int x;

main.h
1
    #ifndef _MAIN_H_
2
    #define _MAIN_H_
3
4
    extern int x;
5
6
    #endif //_MAIN_H_

file1.c
1
    #include "main.h"
2
3
    x=2;

file2.c
1
    #include "main.h"
2
3
    wasweisich = x;

von ohmeiohmei (Gast)


Lesenswert?

> Ich weiss, dass ich bei teil.c & anderer.c die main.h datei entfernen
> muesste, und dafuer ein extern char a,b schreiben muesste. Aber diese
> abtipselei will ich mir sparen.

Ansich wurde schon alles gesagt.
Nur noch ein Tip:
Gegen die "abtipselei" gibt es seit jeher in Windows und anderen 
Betriebssystemen "copy and paste"

von microchip (Gast)


Lesenswert?

thx leute!

ich hab mich jetzt fuer die #define variante mit extern entschieden.

von Randy N. (huskynet)


Lesenswert?

> ich hab mich jetzt fuer die #define variante mit extern entschieden.

Das ist aber trotzdem der falsche Weg. Es gibt einen Unterschied 
zwischen der Deklaration (mit extern) und der Definition (ohne extern) 
der Variable. Die Deklaration besagt nur, dass es die Variable mit dem 
besagten Namen und dem angegebenen Typ irgendwo gibt. Deklarieren kann 
man eine Variable, so oft man will. Die Variable existiert deshalb noch 
nicht. Die Definition hingegen "erstellt" tatsächlich die Variable, sie 
darf deshalb im gesamten Quellcode nur einmal erfolgen. In einer 
Header-Datei sollte deshalb nur die Deklaration (mit extern) erfolgen. 
Jede .c-Datei, in die die Header-Datei included wird, weiß damit, dass 
es die Variable irgendwo gibt. In der main.c würde es sich hier 
anbieten, die Variable auch zu definieren. Das ganze deshalb in der 
main.c, damit es auch wirklich nur einmal passiert. Würdest du die 
Variable in der Header-Datei ohne extern definieren und die Header-Datei 
mehrmals in verschiedene .c-Dateien includen, dann würde die Variable 
eigentlich für jede .c-Datei neu erstellt. Also jede .c-Datei würde dann 
eine andere Variable verwenden, obwohl die gleich heißen. Aber ich glaub 
der Linker wird sich trotzdem beschweren, dass es mehrere globale 
Variablen mit dem gleichen Namen gibt.

Der Weg von Bertram S. ist der einzig richtige.

Grüße
Randy

von Klaus W. (mfgkw)


Lesenswert?

Nein, nicht der einzig richtige.

Abgesehen davon, daß da noch in main.c ein #include "main.h" fehlt
(damit der Compiler Abweichungen erkennen kann), ist es
durchaus legitim und wird auch gelegentlich so gemacht, daß
in der Headerdatei die Variable als extern steht, alle *.c
includen diese und in einer (hier wäre das main.c) steht vor dem
#include "main.h" dann ein #define extern, wodurch das extern
bei diesem #include effektiv verschwindet. Das ist mäßig elegant,
aber oft besser (oder als besser erachtet), als Deklaration und
Definition getrennt zu halten.
Man sollte dann aber nach dem #include nicht das #undef extern
vergessen...

Ich will jetzt nicht behaupten, daß das der irrrsinnig tolle Weg
wäre, aber den gibt es in C leider nicht. Irgendwie muß man
zumindest etwas herummurksen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Klaus Wachtler schrieb:
> [...], daß
> in der Headerdatei die Variable als extern steht, alle *.c
> includen diese und in einer (hier wäre das main.c) steht vor dem
> #include "main.h" dann ein #define extern, wodurch das extern
> bei diesem #include effektiv verschwindet. Das ist mäßig elegant,

und es ist nicht mehr möglich, Initializer für die so definierten 
Variablen zu schreiben, weil dann da steht

int blubb; // aus min.h
int blubb = 1; // aus main.c

Hier ist m.E. an der falschen Stelle gespart.

von P. S. (Gast)


Lesenswert?

Man kann das ganze uebrigens auch ohne extern loesen, indem man 
Zugriffsfunktionen benutzt. Braucht natuerlich ein wenig mehr Codespace. 
Fuer meinen Geschmack wird in der Mikrocontroller-Welt aber viel zu viel 
mit globalen Variablen, die von ueberall her direkt verwendet werden, um 
sich geschmissen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Johann L. (gjlayde) schrieb:

> und es ist nicht mehr möglich, Initializer für die so definierten
> Variablen zu schreiben, weil dann da steht
>
> int blubb; // aus min.h
> int blubb = 1; // aus main.c

Doch, geht, ich mache das schon seit über 20 Jahren so:
1
#ifdef IN_MAIN
2
#define EXTERN
3
#define EXT_INIT(x) = x
4
#else
5
#define EXTERN extern
6
#define EXT_INIT(x)
7
#endif
8
9
EXTERN int blubb EXT_INIT(1);

> Hier ist m.E. an der falschen Stelle gespart.

Deine Meinung, nicht meine. Der Vorteil von Deklaration/Definition an 
einer einzigen Stelle im Source ist für mich unschlagbar.

Gruß,

Frank

von Thomas (Gast)


Lesenswert?

Ich kann mich da nur meinem Vorredner anschliessen und den Zugriff über 
Funktionen machen. Globale Variablen auf die von mehreren Modulen 
zugegriffen werden ist meines Erachtens schlechter Code, schwer 
nachvollziehbar und auch schwer erweiterbar. In meinen Programmen muss 
jedes Modul separat compiliert werden können. Damit ist es auch für 
weitere Projekte wiederverwehrtbar.

Gruß Thomas

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Johann L. (gjlayde) schrieb:
>
>> und es ist nicht mehr möglich, Initializer für die so definierten
>> Variablen zu schreiben, weil dann da steht
>
> Doch, geht, ich mache das schon seit über 20 Jahren so:
>
>
1
> #ifdef IN_MAIN
2
> #define EXTERN
3
> #define EXT_INIT(x) = x
4
> #else
5
> #define EXTERN extern
6
> #define EXT_INIT(x)
7
> #endif
8
> 
9
> EXTERN int blubb EXT_INIT(1);
10
>

Frei flottierende, globale und statische Skalare sind ja so ziemlich die 
Ausnaheme. Zumindest im meinen C-Anwendungen. Ich hab oben nen int 
genommen, um die Problematik aufzuzeigen. IdR wird man in C 
zusammengehörende Sachen in einem Komposit zusammenfassen, so daß 
zusammen steht, was zusammen gehört. Zudem kann man dann nen Zeiger auf 
das "Objekt" übergeben und braucht nicht mit zig Basistypen zu 
hantieren.

Beispiel sind etwa Items in Menü-Steuerungen. Dann gehört zu jedem so 
definierten Komposit also ein eigenes Initializer-Makro... naja.

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.