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 */
Lies ein Anfänger Buch über die Programmiersprache "C". Die ist 40 Jahre alt und alles andere als selbsterklärend.
Du hast eine Definition und keine Deklaration im Headerfile. Schreib ins Headerfile: extern uint8_t a; und in eine C-Datei: uint8_t a;
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.
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.