mikrocontroller.net

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


Autor: microchip (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include "main.h"

main(void)
{
test(a);
tesst(b);
}



teil.c:
#include "main.h"

test(char aaa)
{
a++;
b=aaa;
}


anderer.c:
#include "main.h"
tesst(char bbbb)
{
b++;
a=bbbb;
}

main.h
#ifndef _main_h
#define _main_h
char a,b;
#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 Moderator
Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ;)

Autor: ozo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: der mechatroniker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicht vergessen:

#include "main.h"

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

Autor: Bertram S. (bschall)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
main.c
    int x;

main.h
    #ifndef _MAIN_H_
    #define _MAIN_H_

    extern int x;

    #endif //_MAIN_H_

file1.c
    #include "main.h"

    x=2;

file2.c
    #include "main.h"

    wasweisich = x;

Autor: ohmeiohmei (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: microchip (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
thx leute!

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

Autor: Randy N. (huskynet)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
#ifdef IN_MAIN
#define EXTERN
#define EXT_INIT(x) = x
#else
#define EXTERN extern
#define EXT_INIT(x)
#endif

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

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
>
>
> #ifdef IN_MAIN
> #define EXTERN
> #define EXT_INIT(x) = x
> #else
> #define EXTERN extern
> #define EXT_INIT(x)
> #endif
> 
> EXTERN int blubb EXT_INIT(1);
> 

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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.