Forum: Compiler & IDEs C++ library Variablen includen


von Sep (Gast)


Lesenswert?

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

von Kai S. (zigzeg)


Lesenswert?

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

von Sep (Gast)


Lesenswert?

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?!

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Sep (Gast)


Lesenswert?

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)

von Karl H. (kbuchegg)


Lesenswert?

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
...

von Georg G. (df2au)


Lesenswert?

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.

von Sep (Gast)


Lesenswert?

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'

von Sep (Gast)


Lesenswert?

Natürlich darunter :)
Top und vielen Dank für die Hilfe!

von Georg G. (df2au)


Lesenswert?

setz mal die Definition HINTER die Typdeklaration

von Karl H. (kbuchegg)


Lesenswert?

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.

von zigzeg (Gast)


Lesenswert?

Du musst den Typ erst definieren damit Du ihn benutzen kannst.
Vertausch doch mal die struct ... Zeilen und die extern Deklaration !

ZigZeg

von Sep (Gast)


Lesenswert?

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?

von Fred (Gast)


Lesenswert?

Sep schrieb:
> In Library1.h muss dann die Funktion setzeadresse(unsigned int adresse)
> ebenfalls deklariert werden:

Nein.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Übrigens: Auch wenn hier ständig das Wort "Library" verwendet wird

hier ist nirgendwo eine Library im Spiel

von Karl H. (kbuchegg)


Lesenswert?

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
Noch kein Account? Hier anmelden.