mikrocontroller.net

Forum: Compiler & IDEs Bitfeld verhält sich komisch


Autor: Meike (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Naja (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Naja (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 |)

Autor: Naja (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Meike (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Naja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und was ist mit

#pragma pack(1)

oder

attribute ((packed))


?

Autor: Meike (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Naja,

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

Viele Grüße
Meike

Autor: Marcus Harnisch (mharnisch) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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/

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.