Verschachtelte Strukturen, Union und Bitfelder

Gast #4896866
Hallo zusammen,

habe ein Problem beim Anlegen eines verschachtelten Bitfeldes mit 
Strukturen und Union.

Ziel ist folgendes:
Das gesamte "Konstrukt" soll/darf nur 1 Byte groß sein.
Die Bits 5, 6 und 7 sind ein einzelne Bitfelder (hier: c, b und a).
Die Bits 0+1 (f) sowie 2+3+4 (e) bilden jeweils ein weiteres 
(Zahlen)Feld.
Diese, also die Bits 0 bis 4, sollen zeitgleich auch einen "Gesamtwert" 
repräsentieren (d). Alles zusammen ist eine Kenngröße (g).
1
Bits   7   6   5   4   3   2   1   0
2
     ----------------------------------
3
     |               g                |
4
     ----------------------------------
5
     | a | b | c |         d          |
6
     ----------------------------------
7
                 |     e     |    f   |
8
                 ----------------------

In C sieht das ganze bei mir so aus:
1
typedef union
2
{
3
  struct
4
  {
5
    uint8_t                a : 1;
6
    uint8_t                b : 1;
7
    uint8_t                c : 1;
8
    union
9
    {
10
      struct
11
      {
12
        uint8_t            f : 2;
13
        uint8_t            e : 3;
14
      };
15
      uint8_t              d : 5;
16
    }; 
17
  };
18
  uint8_t                  g;
19
}  TypeID;

Der so definierte Datentyp ist jedoch nicht 1 Byte, sondern 2 Byte groß 
(sizeof(TypeID))! :-O

Begründet liegt das irgendwie an dem inneren Union. Definiere ich das 
ganze so:
1
typedef union
2
{
3
  struct
4
  {
5
    uint8_t                a : 1;
6
    uint8_t                b : 1;
7
    uint8_t                c : 1;      
8
    uint8_t                d : 5; 
9
  };
10
  uint8_t                  g;
11
}  TypeID;
oder so
1
typedef union
2
{
3
  struct
4
  {
5
    uint8_t                a : 1;
6
    uint8_t                b : 1;
7
    uint8_t                c : 1;      
8
    uint8_t                f : 2;
9
    uint8_t                e : 3;
10
  };
11
  uint8_t                  g;
12
}  TypeID;

beträgt die Größe nur 1 Byte.
Klar kann ich jetzt Makros definieren um "d" maskieren und shiften um 
"e" und "f" zur erhalten, das Ganze allerdings direkt über einen Zugriff 
auf Variablen des Datentyps zu lösen ware mir um ein vielfaches lieber.

Wie bekomme ich denn den Datentyp auf 1 Byte !?

Danke für eure Hilfe!

Grüße
Michael
Moderator
Mit dieser Deklaration werden beim GCC die Bitfelder so angeordnet, wie
du es dir vorstellst:

1
typedef union
2
{
3
  struct
4
  {
5
    union
6
    {
7
      struct {
8
        uint8_t  d : 5; // Bit 0..4
9
        uint8_t  c : 1; // Bit 5
10
        uint8_t  b : 1; // Bit 6
11
        uint8_t  a : 1; // Bit 7
12
      };
13
      struct
14
      {
15
        uint8_t  f : 2; // Bit 0..1
16
        uint8_t  e : 3; // Bit 2..4
17
      };
18
    }; 
19
  };
20
  uint8_t        g;     // Bit 0..8
21
} TypeID;

Ein Garantie, dass die Anordnung für einen anderen Compiler ebenso ist,
gibt es aber nicht.

Edit:

Die Größe eines Datentyps ist immer ein ganzzahliges Vielfaches eines
Bytes. Du hast aber wahscheinlich erwartet, dass das dein inneres Struct
nur 5 Bit groß ist.
1
#include <stdio.h>
2
#include <inttypes.h>
3

4
union U
5
{
6
  uint8_t g ;
7
  struct
8
  {
9
    uint8_t d : 5 ;
10
    uint8_t c : 1 ;
11
    uint8_t b : 1 ;
12
    uint8_t a : 1 ;
13
  } abcd ;
14
  struct
15
  {
16
    uint8_t f : 2 ;
17
    uint8_t e : 3 ;
18
  } ef ;
19
} ;
20

21
int main()
22
{
23
  union U u ;
24
  u.g = 0x5d ;
25
  printf("%ld\n",sizeof(u)) ;
26
  printf("%x %x\n",u.ef.e,u.ef.f) ;
27
  printf("%x %x %x %x\n",u.abcd.a,u.abcd.b,u.abcd.c,u.abcd.d) ;
28
  return 0 ;
29
}
Ausgabe:
1
1
2
7 1
3
0 1 0 1d
Imho kann der Compiler aber alles mögliche draus machen. Undefined 
Behavior (at least IB).
Gast
Michael B. schrieb:
> Wie du meinen?


Ich sollte nie vom Handy schreiben...

Also: als erstes klären, ob er mit Bit0 oder mit bit7 anfängt.
1
typedef union
2
{
3
  struct
4
  {
5
    uint8_t                a : 1;
6
    uint8_t                b : 1;
7
    uint8_t                c : 1;
8
    uint8_t                d : 5;
9
  }a_d;
10
  
11
  struct
12
  {
13
      uint8_t              : 3;
14
      uint8_t            e : 3;
15
      uint8_t            f : 2;
16
  }ef;
17
  uint8_t                  g;
18
}  TypeID_MSBstart;
19

20

21
typedef union
22
{
23
  struct
24
  {
25
    uint8_t                d : 5;
26
    uint8_t                c : 1;
27
    uint8_t                b : 1;
28
    uint8_t                a : 1;
29
  }d_a;
30
  
31
  struct
32
  {
33
      uint8_t            f : 2;
34
      uint8_t            e : 3;
35
  }ef;
36
      
37
  uint8_t                  g;
38
}  TypeID_LSBstart;

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.