doppelte definition

Gast #5613229
Lesenswert?

Ich habe ein Problem, das womöglich etwas Einfaches ist.

In einem h-file rechner.h habe ich sowie Funktionsprototypen als auch 
eine Variablendeklaration.

Das Konstrukt sieht so wie angegeben aus.
Wenn ich das File im main.c einbinde mittels include kommt die Meldung 
symbol multiply defined.
Weshalb denn?
Das h-File mit dem Inhalt wird genau an der Stelle eingefügt, wo es im 
main.c steht.
Ich verstehe das Problem irgendwie nicht.

#include "stm32l4xx_hal.h"

/* Define to prevent recursive inclusion 
-------------------------------------*/
#ifndef RECHNER_H
#define RECHNER_H



uint8_t a;

void Rechner_Init (void);
#endif /* RECHNER_H */
Gast #5613368
Lesenswert?

roberto schrieb:
> Wenn ich das File im main.c einbinde mittels include kommt die Meldung
> symbol multiply defined.
> Weshalb denn?

Weil es dir am Grundveständnis fehlt.

Also:
Eigentlich schreibt man erstmal alles, was man in C programmiert, in 
Quellcode-Dateien, die üblicherweise auf .c enden.

Wenn du nun so eine Datei hast, ich nenne die mal ottokar.c, und willst 
aus einer anderen Datei (z.B. aus karlheinz.c) auf eine Funktion (sagen 
wir mal void emil(void)) oder Variable (sagen wir mal int kunigunde ) 
zugreifen, die in ottokar.c steht, dann hast du ein Problem, denn weder 
emil noch kunigunde sind von karlheinz aus sichtbar.

Nun hat C kein Modulsystem wie z.B. Pascal, wo man Dinge, die man aus 
einem Unit heraus der Öffentlichkeit offenbaren will, in die 
'interface'-sektion schreiben kann.

Ersatzesweise gibt es aber als allgemeine Konvention die sogenannten 
Headerfiles, die zumeist auf .h enden. Dort schreibt man all das hinein, 
was man aus der zugehörigen .c der Allgemeinheit offenbaren will. Diese 
.h Datei bindet man dann dort ein, wo man die Informationen benötigt.

Damit das der Compiler auch wirklich als Verweis auf eine andere Datei 
kapiert, schreibt man das Wort 'extern' davor. Bei Funktionen kann man 
das extern auch weglassen, dann wäre es lediglich eine 
Vorwärts-Deklaration, über die sich der C-Compiler jedoch nicht 
beschwert. Ich selber neige dazu, für alles Externe auch immer extern 
davorzuschreiben, ist schlichtweg einheitlicher.

als Beispiel:
in ottokar.h steht
1
#ifndef diesistottokardertoeffel
2
#define diesistottokardertoeffel
3
extern int  kunigunde;
4
extern void emil(void); // hier kannst du das extern weglassen
5
#endif

in ottokar.c steht
1
#include "ottokar.h"
2
int  kunigunde;
3
void emil(void)
4
{ hier irgendwas
5
}

Nun kannst du in karlheinz.c so schreiben:
1
#include "ottokar.h"
2
kunigunde = 1;
3
emil();

Die jeweils eigene .h bindet man zweckmäßigerweise in die .c Datei mit 
ein, damit bei etwaigen Konsistenzfehlern zwischen dem Verweis in .h und 
der eigentlichen Deklaration in .c der Compiler meckern kann.

Wie gesagt, diese .h Headerfiles kann man benutzen, man muß es jedoch 
nicht. Aber es hat sich als Üblichkeit etabliert.

Man kann sie auch benennen wie man will, aber die Endung .h ist auch 
eine Üblichkeit.

Man kann auch die Zeilen mit dem #ifndef xxx.. #define xxx... #endif 
weglassen, muß dann aber selber aufpassen.

Und nochwas:
in eine Headerdatei soll bittesehr nur das hineinkommen, wa man von 
anderen Programmteilen her auch wirklich benötigt - und nicht mehr. Das 
wären die zu exportierenden Variablen und Funktionen und wenn nötig auch 
Typdefinitionen (die brauchen kein 'extern', da sie ja nur einen Typ 
erklären und selber keine Variable sind).
Also keine Romane und keine Interna in .h schreiben.

W.S.
Gast #5613426
Lesenswert?

W.S. schrieb:
> roberto schrieb:


> Man kann sie auch benennen wie man will, aber die Endung .h ist auch
> eine Üblichkeit.
>
> Man kann auch die Zeilen mit dem #ifndef xxx.. #define xxx... #endif
> weglassen, muß dann aber selber aufpassen.
>
> Und nochwas:
> in eine Headerdatei soll bittesehr nur das hineinkommen, wa man von
> anderen Programmteilen her auch wirklich benötigt - und nicht mehr. Das
> wären die zu exportierenden Variablen und Funktionen und wenn nötig auch
> Typdefinitionen (die brauchen kein 'extern', da sie ja nur einen Typ
> erklären und selber keine Variable sind).
> Also keine Romane und keine Interna in .h schreiben.
>
> W.S.

Vielen Dank W.S für die ausfühliche Erklärung.
Das klappt so.
Strukturen benötigen, soviel ich weiss auch keine extern's.
#5613439
Lesenswert?

roberto schrieb:
> Strukturen benötigen, soviel ich weiss auch keine extern's.

Wenn du sowas meinst:
1
struct foo
2
{
3
  uint8_t a;
4
  uint8_t b;
5
};

dann benötigst du kein "extern" da du dem Compiler nur mitteilst, wie 
diese Struktur definiert ist (wie sie aufgebaut ist).

Willst du diese Struktur verwenden, musst du eine Variable vom Typ der 
Struktur anlegen, dabei wird Speicherplatz reserviert und du kannst die 
Variable nutzen:
1
struct foo meine_struktur;

dann benötigst du das extern, wenn du es in die Header schreiben willst.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren