Forum: Mikrocontroller und Digitale Elektronik C: auf globale Variable zugreifen


von Frank (Gast)


Lesenswert?

Hallo zusammen!

Ich habe hier grad ein Problem.

Ich habe eine Funktion in einer ausgelagerten .c-Datei. Die .h ist 
eingebunden. In dieser ausgelagerten .c-Datei möchte ich auf eine 
globale Variable in der main.c zugreifen, aber das klappt bis dato 
nicht. Was muss ich machen?

Irgendwo muss sicher ein extern oder ähnliches hin. Oder welche 
Möglichkeit gibt es noch?

von Hannes H. (mui)


Lesenswert?

main:

int i=0;

andere c-datei:

extern int i;

so müsste das gehen

von Frank (Gast)


Lesenswert?

Nee, tuts nicht, oder ich machs falsch.

von Mani (Gast)


Lesenswert?

Funktioniert es nicht oder gibt es eine Fehlermeldung?
Wenn Fehlermeldung, was für eine?

Grüße

von Hannes H. (mui)


Lesenswert?

Woran merkst du denn, dass es nicht funktioniert? Compilerfehler? 
Funktionale Fehler?
Wo ist dein Quellcode? Bißchen mehr Input wäre hilfreich.

von Frank (Gast)


Lesenswert?

OK, sorry:

main.c
1
...
2
#include andere_datei.h
3
4
struct control
5
{
6
  uint16_t          menu_item;
7
  uint16_t          second_item;
8
  uint16_t          old_menu_item;
9
  uint8_t           item_init;
10
  uint8_t           i_prog;
11
  uint8_t           display_toggle;
12
13
volatile struct control RUNTIME_CONTROL = { 0, 0, 0, FALSE, FALSE, FALSE };
14
15
...
16
17
void main( void )
18
{
19
   ...
20
}

andere_datei.c
1
void funktion_a( void )
2
{
3
  ...
4
}
5
6
void funktion_b( void )
7
{
8
  extern struct RUNTIME_CONTROL;
9
10
  if( RUNTIME_CONTROL.display_toggle )
11
  {
12
    ...
13
  }
14
}

andere_datei.h
1
#ifndef ANDERE_DATEI_H
2
#define ANDERE_DATEI_H
3
4
void funktion_a( void );
5
void funktion_b( void );
6
7
#endif

Fehler: "A storage class may not be specified here"
Und:    "Identifier "RUNTIME_CONTROL" is undefined

von Hannes H. (mui)


Lesenswert?

wenn du in der main
1
volatile struct control RUNTIME_CONTROL = { 0, 0, 0, FALSE, FALSE, FALSE };
anlegst, musst du in andere_datei.c auch auf VOLATILE struct control 
zugreifen:
1
void funktion_b( void )
2
{
3
  extern volatile struct RUNTIME_CONTROL;
4
5
  if( RUNTIME_CONTROL.display_toggle )
6
  {
7
    ...
8
  }

von Frank (Gast)


Lesenswert?

Nee, hab ich auch gedacht, aber das gibt noch ne Warnung mehr:

Warning[Pe021]: type qualifiers are meaningless in this declaration

von Frank (Gast)


Lesenswert?

OK, also generell geht es so. Es muss an dem struct liegen. Nehme ich 
einen einfachen int, dann is alles OK.

von Namehiereingeben (Gast)


Lesenswert?

Wenn der Compiler nicht weiss wie die struct aufgebaut ist kann er auch 
keine Zugriffe auf Elemente davon übersetzen. Den Aufbau der struct hast 
du aber nur in der main.c dem Compiler beschrieben und nicht in der 
andere_datei.c.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Geht das: eine globale Variable lokal zu deklarieren?
Ich hätte gedacht, das muß so aussehen:
1
extern volatile struct RUNTIME_CONTROL;
2
3
void funktion_b( void )
4
{
5
   if( RUNTIME_CONTROL.display_toggle )

von Frank (Gast)


Lesenswert?

Lothar Miller schrieb:
> eine globale Variable lokal zu deklarieren?

Global in der main, nicht in meiner Zusatzfunktion.

von Frank (Gast)


Lesenswert?

OK, die Antwort kann man jetzt auch falsch verstehen...

von Frank (Gast)


Lesenswert?

Namehiereingeben schrieb:
> Wenn der Compiler nicht weiss wie die struct aufgebaut ist kann er auch
> keine Zugriffe auf Elemente davon übersetzen. Den Aufbau der struct hast
> du aber nur in der main.c dem Compiler beschrieben und nicht in der
> andere_datei.c.

Also was muss ich noch machen?

von Sepp (Gast)


Lesenswert?

main.h:
1
struct control
2
{
3
  uint16_t          menu_item;
4
  uint16_t          second_item;
5
  uint16_t          old_menu_item;
6
  uint8_t           item_init;
7
  uint8_t           i_prog;
8
  uint8_t           display_toggle;
9
10
volatile struct control RUNTIME_CONTROL;

in Andere Datei (und in main) dann main.h einbinden. Das mit extern war 
schon richtig

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Frank schrieb:
> Global in der main, nicht in meiner Zusatzfunktion.
Ich hatte da Probleme beim Verständnis der Sichtbarkeit der Variablen... 
;-)

Es reicht aus, wenn diese Deklaration hier
1
struct control
2
{
3
  uint16_t          menu_item;
4
  uint16_t          second_item;
5
  :
6
};
in den andere_datei.h Header kommt, damit der Inhalt des Structs in der 
Funktion bekannt ist.

von Knut (Gast)


Lesenswert?

1
struct control
2
{
3
  uint16_t          menu_item;
4
  uint16_t          second_item;
5
  uint16_t          old_menu_item;
6
  uint8_t           item_init;
7
  uint8_t           i_prog;
8
  uint8_t           display_toggle;
9
}

das packste in die main.h
1
volatile struct control RUNTIME_CONTROL = { 0, 0, 0, FALSE, FALSE, FALSE };

das in die main.c
1
extern volatile struct control RUNTIME_CONTROL
das in die main.h

und dannincludest du die main.h in deine wasauchimmer.h


Knut

von Knut (Gast)


Lesenswert?

Man seit ihr schnell heute....

von Knut (Gast)


Lesenswert?

Sorry, du includest die main.h in deine wasauchimmer.*c*

Knut

von Frank (Gast)


Lesenswert?

Lothar Miller schrieb:
> in den andere_datei.h Header kommt, damit der Inhant des Structs in der
> Funktion bekannt ist.

OK, ich habe jetzt gerade folgendes gemacht:
1
main.c
2
3
...
4
#include andere_datei.h
5
6
struct control
7
{
8
  uint16_t          menu_item;
9
  uint16_t          second_item;
10
  uint16_t          old_menu_item;
11
  uint8_t           item_init;
12
  uint8_t           i_prog;
13
  uint8_t           display_toggle;
14
15
volatile struct control RUNTIME_CONTROL = { 0, 0, 0, FALSE, FALSE, FALSE };
16
17
...
18
19
void main( void )
20
{
21
   ...
22
}

andere_datei.c
1
struct control
2
{
3
  uint16_t          menu_item;
4
  uint16_t          second_item;
5
  uint16_t          old_menu_item;
6
  uint8_t           item_init;
7
  uint8_t           i_prog;
8
  uint8_t           display_toggle;
9
};
10
11
extern volatile struct control RUNTIME_CONTROL;
12
13
void funktion_a( void )
14
{
15
  ...
16
}
17
18
void funktion_b( void )
19
{
20
  extern struct RUNTIME_CONTROL;
21
22
  if( RUNTIME_CONTROL.display_toggle )
23
  {
24
    ...
25
  }
26
}

andere_datei.h
1
#ifndef ANDERE_DATEI_H
2
#define ANDERE_DATEI_H
3
4
void funktion_a( void );
5
void funktion_b( void );
6
7
#endif

Ich habe das struct also nochmal in die andere .c-Datei gepackt - 
scheint auch erstmal zu gehen? Wo ist jetzt der Unterschied es in die 
.h- oder .c-Datei zu packen?

von Frank (Gast)


Lesenswert?

Knut schrieb:
> das packste in die main.h

Sorry, aber was denn für eine main.H ? Hab ich nicht ;-)

von Knut (Gast)


Lesenswert?

Dann mach dir eine...

Wenn du den Prototypen in der main.h machen würdest, dass eigentlich 
Struct in der main.c dann deklarierst, kannst du in anderen Files auf 
das Struct zugreifen, wenn du dort die main.h includierst. Vorher musst 
du natürlich noch in der main.h dein in der main.c deklariertes Struct 
als extern deklarieren.

Dann klappts auch mit den Nachbarfiles...


Knut

von Frank (Gast)


Lesenswert?

OK, kann mir denn noch einer sagen, wo der Unterschied ist, ob ich
1
// andere_funktion.h
2
3
struct control
4
{
5
  uint16_t          menu_item;
6
  uint16_t          second_item;
7
  uint16_t          old_menu_item;
8
  uint8_t           item_init;
9
  uint8_t           i_prog;
10
  uint8_t           display_toggle;
11
};
12
13
extern volatile struct control RUNTIME_CONTROL;
oder
1
// andere_funktion.c
2
3
struct control
4
{
5
  uint16_t          menu_item;
6
  uint16_t          second_item;
7
  uint16_t          old_menu_item;
8
  uint8_t           item_init;
9
  uint8_t           i_prog;
10
  uint8_t           display_toggle;
11
};
12
13
extern volatile struct control RUNTIME_CONTROL;

mache?

von Detlev T. (detlevt)


Lesenswert?

Ist das nicht nur ein Syntax-Fehler, weil das struct control einfach nie 
geschlossen wird (Klammer fehlt)?

von Frank (Gast)


Lesenswert?

Detlev T. schrieb:
> Ist das nicht nur ein Syntax-Fehler, weil das struct control einfach nie
> geschlossen wird (Klammer fehlt)?

Nee, das war ein Kopierfehler ;-)

von Frank (Gast)


Lesenswert?

Hab ich es denn jetzt richtig, oder klappt es grad nur aus gut Glück?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> OK, kann mir denn noch einer sagen, wo der Unterschied ist, ob ich
> // andere_funktion.h ...
> oder
> // andere_funktion.c ...
> mache?
Vermutlich steht in andere_datei.c auch das hier:
#include andere_datei.h

Und damit wäre der Struct sowohl in main.c wie auch in andere_date.c 
bekannt. Überall eben, wo er verwendet wird. Und darauf kommt es an.

von Karl H. (kbuchegg)


Lesenswert?

Frank schrieb:
> OK, kann mir denn noch einer sagen, wo der Unterschied ist, ob ich

Stell dir einfach mal vor du machst das hier

main.c
1
struct control
2
{
3
  uint8_t   abc;
4
  uint16t   def;
5
};
6
7
struct control globvar;
8
9
int main()
10
{
11
  globvar.abc = 8;
12
  globvar.def = 16;
13
14
  foo();
15
}

andere.c
1
struct control
2
{
3
  double    abc;
4
  uint16t   def;
5
};
6
7
extern struct control globvar;
8
9
void foo()
10
{
11
  globvar.abc = 42.0
12
}

Grundsätzlich ist das von der Vorgehensweise her richtig. Jedes C-File 
ist in sich vollständig und hat alles was es braucht.
Aber: Die Strukturdefinitionen in den beiden C-Files stimmen NICHT 
überein. Das kann zb passieren, wenn man eine Strukturdefinition im 
Nachhinein noch erweitert oder umbaut.

Der Compiler kann dich davor nicht schützen! Der sieht sich immer nur 1 
C-File an. Was im anderen drinnen ist, interessiert ihn nicht.

Das wäre aber ein schwerer Fehler, wenn die Strukturaufbauten nicht 
übereinstimmen!

So rum

irgendwas.h
1
struct control
2
{
3
  double    abc;
4
  uint16t   def;
5
};
6
7
extern struct control globvar;

main.c
1
#include "irgendwas.h"
2
3
struct control globvar;
4
5
int main()
6
{
7
  globvar.abc = 8;
8
  globvar.def = 16;
9
10
  foo();
11
}

andere.c
1
#include "irgendwas.h"
2
3
void foo()
4
{
5
  globvar.abc = 42.0
6
}

kann dir dieser Fehler aber nicht passieren.
Dadurch, dass die eigentliche Strukturdefinition nur an EINER Stelle 
steht und überall wo sie gebraucht wird inkludiert wird, vermeidest du 
ganz einfach diesen Fehler.
Hier ist das verschieben in ein Header File also Selbstschutz um dich 
selbst vor Fehlern zu schützen.

von Namhiereingeben (Gast)


Lesenswert?

Frank schrieb:
> OK, kann mir denn noch einer sagen, wo der Unterschied ist, ob ich// 
andere_funktion.h
(...)
> oder// andere_funktion.c
(...)
> mache?

Sofern du die andere_funktion.h in die andere_funktion.c mittels 
#include eingebunden hast ist da zunächst kein Unterschied - die 
#include-Anweisung sorgt im Compiler lediglich dafür, dass der Inhalt 
der angegebenen Datei an der Stelle des #include 1:1 eingelesen wird als 
ob man ihn direkt hingeschrieben hätte. Die struct in der .h zu 
definieren hat allerdings den Vorteil, dass man die .h-Datei noch in 
andere Dateien includen kann (z.B. in der main.c) und dort dann 
ebenfalls eine Definition dieser struct hat, ohne den Text der die 
struct beschreibt selbst in mehrere Dateien reinschreiben zu müssen.

Neben einem Hauch von Arbeitserleichterung verringert das auch die 
Wahrscheinlichkeit eines Fehlers: Da nur an einer Stelle Änderungen 
vorgenommen werden müssen um automatisch alle Verwendungen zu ändern 
besteht nicht das Risiko, dass man die Änderung in irgendeiner .c-Datei 
vergisst.

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.