C: auf globale Variable zugreifen

Gast #2143570
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?
Gast #2143639
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
#2143656
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
  }
Gast #2143677
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.
Gast #2143691
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
Moderator (Firma: Titel) Persönliche Seite #2143692
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.
Gast #2143694
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
Gast #2143705
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?
Gast #2143727
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
Gast #2143741
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?
Moderator (Firma: Titel) Persönliche Seite #2143777
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.
#2144016
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.
Gast #2144020
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.

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