Forum: Compiler & IDEs Bitfeld verhält sich komisch


von Meike (Gast)


Lesenswert?

Hallo Leute,

ich suche eine Möglichkeit einer 32 Bit großen Zahl ein Bitmuster 
zuzuweisen. Das ganze für Microchip C18.

Ich habe es über eine union folgendermaßen versucht.


union _Bits {
  unsigned long int alle;

  struct _Bits_alle {
    unsigned   B1      :1 ;
    unsigned   B2      :1 ;
    unsigned   B3      :7 ;
    unsigned   B4      :1 ;
    unsigned   B5      :6 ;
    unsigned   B6      :1 ;
  };
}Bits;


Wenn ich jetzt Bits.alle auf 0 setze, anschließend z.b. Bits.B1 = 1 
setze, steht in Bits.alle wie erwartet folgendes (binär):
00000000000000000000000000000010

Wenn ich jedoch statt dem einen Bit von B1 die 7 Bits von B3 auf 1111111 
setze, steht in Bits.alle
00000000000000000111111100000000

und nicht wie ich es erwartet hätte
00000000000000000000000111111100


Es scheint so als würde der Compiler alles in 8 Bit zerlegen. Weil 8-2=6 
zu klein ist für 7 Bits macht er erst beim 9ten Bit weiter. 
Versuchsweise habe ich die Anzahl der Bits von 7 auf 6 geändert, dann 
hat es geklappt. Ich brauche aber 7 Bit.

 Ich hoffe ihr versteht was ich meine und könnt mir helfen.


Wie mache ich es also, dass ich genau das bekomme was ich erwarte?


Viele Grüße
Meike

von Naja (Gast)


Lesenswert?

Schau mal in der Compilerdokumentation ob Du

#pragma pack(1)

oder

_attribute_ ((packed))

verwenden musst bzw. kannst.

Einen Schritt vom Bild zurückgetreten gibt es noch eine weitere 
Möglichkeit, die dann aber keine Benennung der Bits zulässt. So lässt 
sich das Nulte Bit in einem unsigned int etwas mit 0x01 oder das vierte 
mit 0x10 setzen.

Übrigens decken Sich meine Erwartungen bei Deiner Deklaration nich mit 
Deinen. Mit Bits.B1 = 1 würde ich 00000...00001 als binärwert erwarten 
und nicht 0000...000010, da kein "nulltes" Bit deklarieriert ist.

von Naja (Gast)


Lesenswert?

Abgesehen davon, solltest Du klären wie Du zu Deiner Erwartung kommst. 
Das Verhalten bei Bitfeldern ist nämlich strikt Compilerabhängig und in 
keinem Standard festgelegt.

von Karl H. (kbuchegg)


Lesenswert?

Meike schrieb:

> und nicht wie ich es erwartet hätte
> 00000000000000000000000111111100
>
>
> Es scheint so als würde der Compiler alles in 8 Bit zerlegen.

Scheint so.
Der Compiler darf das auch. Du hast keine Kontrolle darüber, wie genau 
er die Bits anordnet.
genausowenig, wie du auch die Kontrolle darüber hast, an welchen Stellen 
exakt ein Compiler Strukturelemente anordnet. Er darf Padding Bytes 
einfügen. Und in deinem Fall hat er eben 'padding bits' eingefügt. Der 
Compiler wird das auch in guter Absicht gemacht haben um damit die 
Zugriffe zu vereinfachen :-)

>  Ich hoffe ihr versteht was ich meine und könnt mir helfen.

Du könntest mal versuchen, dein Bitfeld auf 32 Bits mit einem Dummyfeld 
aufzublasen. Dann bleibt dem Compiler nichts anderes mehr übrig, als die 
7 Bits so anzuordnen wie du das haben möchtest. Lass ihm kein 
Schlupfloch!

> Wie mache ich es also, dass ich genau das bekomme was ich erwarte?

Schlimmstenfalls musst du das selber machen. Per Bitshift und 
Bitoperationen (& und |)

von Naja (Gast)


Lesenswert?

Ich habe mir da selbst widersprochen. Einerseits "erwarte" ich 
0000...00001 anstell von 0000...000010, andererseits weise ich darauf 
hin, das dies Compilerabhängig ist. Letzteres ist maßgebend, wenn man 
auch oft auf das erstere trifft.

von Meike (Gast)


Lesenswert?

Hallo,

danke für die schnellen Antworten.

Karl Heinz das mit dem Auffüllen auf 32 Bit habe ich versucht. Leider 
führt das zum gleichen Ergebnis. Was eigentlich komisch ist.

Ich werde wohl wirklich auf die Bitoperationen zurückgreifen und es 
selber machen. Es wäre ja auch zu schön gewesen...


Viele Grüße
Meike

von Naja (Gast)


Lesenswert?

Und was ist mit

#pragma pack(1)

oder

attribute ((packed))


?

von Meike (Gast)


Lesenswert?

Hallo Naja,

das kenne ich leider nicht. Ich werde nachlesen was du meinst und es 
damit versuchen. Danke

Viele Grüße
Meike

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Meike schrieb:
> union _Bits {
>   unsigned long int alle;
>
>   struct _Bits_alle {
>     unsigned   B1      :1 ;
>     unsigned   B2      :1 ;
>     unsigned   B3      :7 ;
>     unsigned   B4      :1 ;
>     unsigned   B5      :6 ;
>     unsigned   B6      :1 ;
>   };
> }Bits;

Hast Du mal versucht, die Bitfelder ebenfalls als unsigned long zu 
deklarieren? Ich kenne die Typ-Repräsentation der PIC Familie nicht, 
aber könnte mir das durchaus als Ursache vorstellen. Falls es irgendwo 
eine ABI Dokumentation für PIC gibt, sollte die Begründung für das 
beobachtete Verhalten da drin stehen.

Lass Dich nicht unterkriegen -- bit fields rule! :-)

Gruß
Marcus
http://www.doulos.com/arm/

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.