Forum: Compiler & IDEs ? zu Zugriff auf union


von Thomas P. (topla)


Lesenswert?

Hallo zusammen,
ich habe für mein Projekt mal etwas mit unions herumprobiert und 
versucht, Beispiele nachzuvollziehen und für anzupassen.
Bei folgendem Beispiel
1
#include <stdint.h>
2
typedef struct
3
{
4
  uint8_t gzio: 1;
5
  uint8_t input: 1;
6
  uint8_t adr: 6;
7
} gzi_dat_t;
8
9
typedef union
10
  {
11
    gzi_dat_t gzi_dat;
12
  uint8_t gzi_bytes;
13
  } gzi_union_t;
14
15
gzi_union_t gzi[32];
16
17
int main(void)
18
{
19
uint8_t i;
20
  for (i=0; i<32; i++) gzi.gzi_bytes[i] = 0;
21
  
22
  while(1);
23
}

erhalte ich diesen Fehler:
../main.c:41:26: error: request for member 'gzi_bytes' in something not 
a structure or union

und weiß nicht, welchen Fehler ich gemacht habe.
Könnte mir bitte jemand weiterhelfen?

Danke
Thomas

von B. S. (bestucki)


Lesenswert?

Du meinst wohl:
1
for (i=0; i<32; i++) gzi[i].gzi_bytes = 0;
2
                        ^^^

: Bearbeitet durch User
von Brolev (Gast)


Lesenswert?

gzi.gzi_bytes[i] gibt es nicht in deinem Chaosprogramm.

von B. S. (bestucki)


Lesenswert?

Und noch was anderes:
Ich vermute, dass du die union mit dem einen Member setzen und durch den 
anderen lesen willst. Das endet in undefiniertem Verhalten. So wie ein 
Bitfeld nach Standard nur mit den Typen _Bool, int und unsigned int 
definiert werden darf (siehe 
https://www.mikrocontroller.net/articles/Bitfelder). Ausserdem müsstest 
du noch dafür sorgen, dass das Alignment der struct korrekt ist, die 
ganze Sache wäre für diesen Zweck alles andere als portabel...

: Bearbeitet durch User
von Thomas P. (topla)


Lesenswert?

Das war's. Vielen Dank für den Blindenhund.
Deine Vermutung stimmt auch, geschrieben werden die Bits im Programm und 
später im eeprom gesichert. Ich verstehe jetzt nicht, warum das in 
undefiniertem Verhalten enden soll. Details zur Definition der Bitfelder 
muss ich mir noch mal anlesen, da bin ich wohl einem falschen Beispiel 
aufgesessen. Sollte man diese Bitzugriffe besser auf Bitmanipulation mit 
and und or umstellen?

Thomas

von B. S. (bestucki)


Lesenswert?

Thomas P. schrieb:
> Ich verstehe jetzt nicht, warum das in
> undefiniertem Verhalten enden soll.
Weil das so im Standard steht. Mit vielen Compilern funktioniert das 
wahrscheinlich wie gewünscht, ab einer neuen Compilerversion treten 
vielleicht plötzlich Fehler auf, die dich verzweifeln lassen...

Thomas P. schrieb:
> Details zur Definition der Bitfelder
> muss ich mir noch mal anlesen, da bin ich wohl einem falschen Beispiel
> aufgesessen.
Wenn du den Code nur mit einem Compiler verwendest, der diese Definition 
akzeptiert, ist alles in Ordnung. Du musst dir einfach bewusst sein, 
dass dein Code dann nicht portabel ist. Auch bei kleinen 
Mikrocontrollern ist der erhöhte Speicherverbrauch (z.B. 2 statt 1 Byte) 
meist kein Problem. Wenn doch, kann man immer noch die nicht portable 
Version verwenden.

Thomas P. schrieb:
> Sollte man diese Bitzugriffe besser auf Bitmanipulation mit
> and und or umstellen?
Ja. Ist in deinem Fall auch nicht sehr aufwändig. Ich würde bei deinem 
Beispiel Funktionen zur Konvertierung von uint8_t zu gzi_dat_t und 
umgekehrt schreiben.

P.S: Wenn wir schon beim Thema Portabilität sind: Die (u)intXX_t-Typen 
sind nicht portabel, da die vom Standard nicht zwingend verlangt werden 
(es existieren Plattformen, auf denen uint8_t nicht vorhanden ist). 
Stattdessen besser (u)int_leastXX_t zum Speichern von Werten und 
(u)int_fastXX_t für Berechnungen verwenden.

von Thomas P. (topla)


Lesenswert?

Danke für die ausführlichen Informationen. Da werde ich mal den Umbau 
der Bitzugriffe in Angriff nehmen.

Thomas

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.