Hallo, ich hab eine vermutlich einfache Frage bzgl. C Programmierung. Ich habe eine Funktion main.c und eine test.c und test.h In test.h deklariere ich mir eine Variable unsigned int haus und nutze Sie in test.c. Weiterhin habe ich eine test2.h und test2.c In test2.c include ich test.h und würde dort jetzt auch gerne die Variable haus nutzen. Ich bekomme immer die Fehlermeldung: error: 'haus' undeclared (first use in this function) Was muss ich beachten? Merci
So geht's richtig: In haus.h:
1 | extern unsigned int haus; |
in haus.c:
1 | #include "haus.h" |
2 | unsigned int haus=0; |
In anderen modulen (z.B. main.c, test2.c):
1 | #include "haus.h" |
Apropos, irgendwie passt Dein Fehler und Deine Beschreibung nicht zusammen ! ZigZeg
Danke ZigBe Warum passt das nicht zusammen? Haus ist nicht die Library, sondern der Name der Variable Also in .h immer die Deklarierung und in .c immer noch defnieren. Extern Schlüsselwort, damit ich die Variable auch in "externen" Librarys nutzen kann?!
Sep schrieb: > Danke ZigBe > > Warum passt das nicht zusammen? Wenn du DEINEN Code zeigen würdest, dann könnte man dir sagen, wo du den Fehler gemacht hast. So wie ZigBe das vorgezeigt hat, ist es richtig.
Sep schrieb: > Also in .h immer die Deklarierung und in .c immer noch defnieren. Im Prinzip: ja > Extern Schlüsselwort, damit ich die Variable auch in "externen" Librarys > nutzen kann?! Nein. 'extern' Schlüsselwort, damit das eine Deklaration ist und keine Definition.
OK hier der Code: library1.h
1 | ...
|
2 | typedef struct |
3 | {
|
4 | unsigned long a; // uint_least32_t |
5 | unsigned long b; |
6 | unsigned long c; |
7 | unsigned long d; |
8 | unsigned long e; |
9 | unsigned long f; |
10 | unsigned long g; |
11 | } TYP_M; |
12 | ...
|
library1.c
1 | ...
|
2 | TYP_M tc_variable |
3 | ...
|
4 | void setze(void) |
5 | {tc_variable.a = 0;} |
library2.c
1 | #include "library1.h" |
2 | void machewas(void) |
3 | {tc_variable.a = 0;} |
Ergebnis: error: 'tc_variable' undeclared (first use in this function)
Und wo ist da jetzt die extern Deklaration der Variablen im Header File?
1 | ...
|
2 | typedef struct |
3 | {
|
4 | unsigned long a; // uint_least32_t |
5 | unsigned long b; |
6 | unsigned long c; |
7 | unsigned long d; |
8 | unsigned long e; |
9 | unsigned long f; |
10 | unsigned long g; |
11 | } TYP_M; |
12 | |
13 | |
14 | extern TYP_M tc_variable; |
15 | ...
|
Sep schrieb: > 'tc_variable' undeclared Wieso wundert dich das? hast du tc_variable in library1.h als extern deklariert? Ich sehe nur die Definition der Struktur, nicht die Variable.
Wie oben beschrieben hätte ich vermutet, dass es heissen müßte: library1.h
1 | ...
|
2 | extern TYP_M tc_variable; |
3 | typedef struct |
4 | {
|
5 | unsigned long a; // uint_least32_t |
6 | unsigned long b; |
7 | unsigned long c; |
8 | unsigned long d; |
9 | unsigned long e; |
10 | unsigned long f; |
11 | unsigned long g; |
12 | } TYP_M; |
13 | ...
|
library1.c
1 | TYP_M tc_variable; |
Das funktioniert aber auch nicht -> error: expected '=', ',', ';', 'asm' or '__attribute__' before 'tc_variable'
Sep schrieb: > Wie oben beschrieben hätte ich vermutet, grrr. du sollst nicht vermuten, sondern deine Programmiersprache LERNEN. Der COmpiler liest den Code von oben nach unten. Und zwar nur ein einziges mal. Du kannst nur Dinge verwenden, die schon bekannt sind (bis auf die C-Standard Sachen, die kennt der Compiler immer). D.h. hier
1 | extern TYP_M tc_variable; |
fragt sich der Compiler: Hä? TYP_M, was für ein TYP_M? Von einem TYP_M hab ich noch nie etwas gehört. Da werf ich mal eine Fehlermeldung. Warte mal. An dieser Stelle kann nicht der Name einer Variablen stehen, da müsste ein Datentyp stehen. TYP_M ist nicht der Name eines Datentyps. Ich schlag mal was vor, was meiner Meinung da jetzt eigentlich stehen müsste. Das du danach dann definierst, was ein TYP_M ist, ist uninteressant. Der Compiler liest den Code von oben nach unten und stösst somit zwangsläufig zuerst auf die Verwendung und erst dann auf die Definition, was das eigentlich sein soll. Es muss aber umgekehrt sein, erst die Definition und erst dann die Verwendung, damit der Compiler bei der Verwendung auch weiß, wie groß das Teil im Speicher ist.
Du musst den Typ erst definieren damit Du ihn benutzen kannst. Vertausch doch mal die struct ... Zeilen und die extern Deklaration ! ZigZeg
Hallo und Danke für die ganzen Antworten. Wie funktioniert das mit Funktionen. Es handelt sich wieder um eine library2.h
1 | unsigned char setzeadresse(unsigned int adresse); |
In library2.c
1 | #include "library2.h" |
2 | unsigned char setzeadresse(unsigned int adresse) |
3 | {
|
4 | ...
|
5 | }
|
In der Library1.c soll nun eine Funktion genutzt werden, die setzeadresse() aufruft. In etwa so
1 | #include "library2.h" |
2 | void rufeauf(void) |
3 | {
|
4 | ...
|
5 | setzeadresse(adresse) |
6 | ...
|
7 | }
|
In Library1.h muss dann die Funktion setzeadresse(unsigned int adresse) ebenfalls deklariert werden:
1 | unsigned char setzeadresse(unsigned int adresse); |
In der Main.c wird jetzt die Funktion rufeauf() aufgerufen. Es muss sowohl library1.h als auch library2.h includiert werden:
1 | #include "library2.h" |
2 | #include "library1.h" |
3 | |
4 | rufeauf(); |
Ist dies alles so korrekt?
Sep schrieb: > In Library1.h muss dann die Funktion setzeadresse(unsigned int adresse) > ebenfalls deklariert werden: Nein.
Übrigens: Auch wenn hier ständig das Wort "Library" verwendet wird hier ist nirgendwo eine Library im Spiel
Sep schrieb: > In der Main.c wird jetzt die Funktion rufeauf() aufgerufen. Es muss > sowohl library1.h als auch library2.h includiert werden: wozu 'library1.h' Was die Funktion rufeauf() intern macht interessiert doch an dieser Stelle überhaupt nicht
1 | int main() |
2 | {
|
3 | rufeauf(); |
4 | }
|
das einzige was hier interessant ist, ist die Fragestellung: wie ist das mit der Funktion rufeauf? * Will die Argumente haben, ja oder nein. Wenn ja, wieviele und welche Datentypen. * Hat die Funktion einen Rückgabewert und wenn ja von welchem Datentyp ist der? Mit dem Prototyp in 'library2.h'
1 | void rufeauf( void ); |
sind beide Fragen beantwortbar. Daher ist das völlig ausreichend. Das die Funktion ihrerseits wieder andere Funktionen aufruft, ist zwar schön, aber für den Aufruf der Funktion rufeauf in main komplett irrelevant. Einfach mal ein bischen mitdenken und durchspielen, warum die Dinge so sind wie sie sind und welchen Zweck sie erfüllen. Versetz dich einfach mal gedanklich in die Lage des Compilers, der jeden Funktionsaufruf kontrollieren möchte. Und dann überlegst du dir: wo und wie kriege ich die Information dafür her bzw. welche Information benötige ich an einer bestimmten Stelle bzw. welche Information benötige ich nicht?
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.