Forum: Compiler & IDEs Struktur Bitfeld in Variable kopieren


von bernd (Gast)


Lesenswert?

Guten Tag

Ich schlag mich so ein bisschen mit Strukturen herum und bin etwas 
genervt.
Genaugenommen geht es im Bitfeldern die ich so definiert habe.

int main()
  {
    struct
    {
      unsigned char status:1; // 1 Bit für bStatus_1
      unsigned char status1:1; // 1 Bit für bStatus_1
      unsigned char status2:1; // 1 Bit für bStatus_1
      unsigned char status3:1; // 1 Bit für bStatus_1
      unsigned char status4:1; // 1 Bit für bStatus_1

    } byte;


  while(1)
    {
    }
  }

Das funktioniert aus soweit ganz gut, mit bit.status1 u.s.w kann ich 
alles mit den bits machen.

Jetzt dachte ich ich könnte die so veränderten bits nun in den Porta 
schreiben.
Also PORTA = byte; // Der Inhalt von byte wird in den PORTA kopiert

geht aber nicht?? Warum, oder wie geht das kopieren.

Danke

von Werner B. (Gast)


Lesenswert?

PORTA = *((unsigned char *)&byte);

von Johannes M. (johnny-m)


Lesenswert?

oder mit einer union... Man muss sich aber bei beiden Varianten klar 
darüber sein, dass der C-Standard nicht definiert, in welcher 
Reihenfolge die Bits in einem Bitfeld abgelegt werden. Ausprobieren...

von OliverSo (Gast)


Lesenswert?

Die union-Variante geht dann z.B. so:
1
  union
2
  {
3
  struct
4
    {
5
      unsigned char  status:1;
6
      unsigned char  status1:1;
7
      unsigned char  status2:1;
8
      unsigned char  status3:1;
9
      unsigned char  status4:1;
10
    };
11
    unsigned char byte;
12
  } bit_byte;
13
14
 bit_byte.status = 1;
15
 PORTA = bit_byte.byte;

Oliver

von Johannes M. (johnny-m)


Lesenswert?

OliverSo wrote:
> Die union-Variante geht dann z.B. so:
> [...]
Exakt. Der AVR-GCC legt übrigens afaik die einzelnen Bitfeld-Elemente 
"von hinten" ab, also das erste Element des Bitfeldes (im Beispiel 
status ) am niederwertigen Ende des Bytes (also im Bit Nummer 0).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Die genannte Variante ist IMHO nicht portabel, sondern eine GCC-
Erweiterung.  Die portable Variante müsste der bitfield-struct
noch einen Namen geben:
1
union
2
{
3
struct
4
  {
5
    unsigned char  status:1;
6
    unsigned char  status1:1;
7
    unsigned char  status2:1;
8
    unsigned char  status3:1;
9
    unsigned char  status4:1;
10
  } bits;
11
  unsigned char byte;
12
} bit_byte;
13
14
 bit_byte.bits.status = 1;
15
 PORTA = bit_byte.byte;

von Johannes M. (johnny-m)


Lesenswert?

Jörg Wunsch wrote:
> Die genannte Variante ist IMHO nicht portabel, sondern eine GCC-
> Erweiterung.  Die portable Variante müsste der bitfield-struct
> noch einen Namen geben:
Stimmt natürlich. Das hatte ich übersehen. Funktioniert das ohne Namen 
im GCC tatsächlich?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Johannes M. wrote:

> Funktioniert das ohne Namen
> im GCC tatsächlich?

Ja. ;-)

http://gcc.gnu.org/onlinedocs/gcc-4.2.3/gcc/Unnamed-Fields.html#Unnamed-Fields

von bernd (Gast)


Lesenswert?

Hallo, schon mal danke, ich werde die Sachen mal ausprobieren. Ich finde 
es ein bisschen Schade das gcc von Standarts abweicht die sich bei 
(teuren) Compilern so eingebürgert haben. Z.B. macht Keil das mit " 
#byte " und " #bit ". Das ist sehr einfach und spart Programmierarbeit. 
Habe bisher die Assembler Technik genutzt und Bits numeriert um sie 
später mit einem Byte zu maskieren. Aber mit "if(Byte & (1<<Bit)) u.s.w" 
bricht man sich die Finger.

unsigned int abzukürzen ist ja ganz toll, aber uint16_t ist auch nicht 
der Hit, wenn man nicht blind zehn Finger schreiben kann.

Zugegeben haben Strukturen mehr Möglichkeiten, aber bits zu setzen finde 
ich so wichtig das man den Elektrotechniker und Nichtinformatiker ein 
bisschen unterstützen sollte.

von Johannes M. (johnny-m)


Lesenswert?

bernd wrote:
> Hallo, schon mal danke, ich werde die Sachen mal ausprobieren. Ich finde
> es ein bisschen Schade das gcc von Standarts abweicht die sich bei
> (teuren) Compilern so eingebürgert haben.
Falsch ! Das sind eben keine Standards, sondern willkürliche 
Erweiterungen einiger kommerzieller Embedded-C-Compiler, die nicht vom 
ANSI-Standard abgedeckt sind. Außerdem kocht da praktisch jeder Anbieter 
sein eigenes Süppchen, weshalb die Sachen auch bei einer Plattform 
i.d.R. nicht portierbar sind.

Der AVR-GCC ist im Großen und Ganzen ein ANSI-C-Compiler, der zwar 
mittlerweile auch einige µC-spezifische Erweiterungen bietet, die für 
notwendig bzw. wirklich sinnvoll erachtet wurden (z.B. Eingabe von 
Binärzahlen mit 0bxxxx), die aber vom ANSI-Standard nicht abgedeckt 
werden. Ansonsten kommt man gar nicht erst in Versuchung, Code zu 
schreiben, den andere C-Compiler nicht verstehen. Hier im Forum tauchen 
des öfteren Anfragen auf nach dem Motto "Hilfe! Habe Programm für 
Compiler XYZ geschrieben und es lässt sich mit Compiler ZYX nicht 
compilieren...". Die Standard-konformen Schreibweisen versteht jeder 
C-Compiler, der den Namen zu Recht trägt. Einzige Ausnahme bilden dann 
allerdings trotz allem die µC-spezifischen Bibliotheksfunktionen.

Die meisten "Vereinfachungen" der kommerziellen Compiler täuschen auch 
darüber hinweg, was im Hintergrund abläuft. Und das kann gerade bei 
Hardware-nahen Anwendungen schonmal zu langen Fehlersuchen führen, wenn 
man als Programmierer nicht mal weiß, was da eigentlich passiert.

von Karl H. (kbuchegg)


Lesenswert?

bernd wrote:

> später mit einem Byte zu maskieren. Aber mit "if(Byte & (1<<Bit)) u.s.w"
> bricht man sich die Finger.
....
> Zugegeben haben Strukturen mehr Möglichkeiten, aber bits zu setzen finde
> ich so wichtig das man den Elektrotechniker und Nichtinformatiker ein
> bisschen unterstützen sollte.

Was hindert dich daran, dir selbst mit Standard-C ein paar
Hilfsfunktionen bzw. Makros zu schreiben, so dass du dir nicht
mehr die Finger brichst?

Im Übrigen wird die reine Tipparbeit überschätzt. Das Problem
beim Programmieren ist ja nicht das Drücken von Tasten sondern
die Logik die es umzusetzen gilt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

bernd wrote:

> Aber mit "if(Byte & (1<<Bit)) u.s.w"
> bricht man sich die Finger.

Das eigentliche Übel ist, dass die Bitkonstanten nicht gleich als
Masken definiert worden sind, sondern als Bitnummern.  Das wiederum
hat seine Ursache darin, dass die entsprechenden Bitnamen auch in
Assemblercode verwendbar sein sollten, und dass dort Befehle wie
CBI oder SBI eine Bitnummer brauchen.  Von einer Nummer auf eine
Maske ,,rechnen'' ist trivial, eine Maske in eine Nummer zurückzu-
rechnen leider nicht.

Du kannst dir das 1<< ja in einem Makro vereinfachen.  avr-libc bietet
dir dafür den Makro _BV() bereits vorgefertigt an.

> unsigned int abzukürzen ist ja ganz toll, aber uint16_t ist auch nicht
> der Hit, wenn man nicht blind zehn Finger schreiben kann.

Das ist aber C99-Standard.  Es hat nichts mit ,,abkürzen'' zu tun,
sondern besagt, dass der entsprechende Datentyp unabhängig von der
verwendeten Umgebung eben genau 16 bits breit (und vorzeichenlos)
ist.  Das ist für "unsigned int" nicht gegeben, das kann durchaus auch
32 bits breit sein.

von bernd (Gast)


Lesenswert?

OK OK OK
mit Standarts meinte ich jetzt nicht das es quasi genormt ist, sondern 
wie ja schon gesagt wurde sich um -> sinnvolle <- Erweiterungen handelt, 
die aber bei jeden teuern Compiler eben vorhanden sind.

Ich habe das mal ausprobiert und die Strukturen lassen sich nicht 
vernümftig watchen. Es wird bei jedem Bit der Byte Wert angezeigt.
Zum Debuggen mist, da sich die Bits auch nicht immer mit den Werten 
setzen lassen (1,2,4,8 u.s.w).
Ach ja, ich nutze AVR Studio mit gcc.

Werde wohl doch wieder maskieren. Son shit. Habe mal einem Informatiker 
über die Finger geschaut, da bekommt man ja Augenkrebs. Die nehmen auch 
für alles Bytes, ist ja auch egal.

von Karl H. (kbuchegg)


Lesenswert?

Pssss bernd

Ist jetzt nicht wirklich wichtig, aber es heist Standard. Hinten
mit 'd'.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

bernd wrote:

> wie ja schon gesagt wurde sich um -> sinnvolle <- Erweiterungen handelt,
> die aber bei jeden teuern Compiler eben vorhanden sind.

Du kennst ,,jeden teuren'' Compiler?

Ich kenne zumindest einen, der zu den teuersten zählt (und vom
generierten Code her zu den besten), aber der hält sich mit allem
an den C-Standard und die durch den Standard vorgegebenen
Syntaxregeln der Sprache.  Das bedeutet nicht, dass er keine
Erweiterungen hätte (die hat wohl jeder Compiler), aber er bewegt
sich mit seinen Erweiterungen (genauso wie GCC) zumindest im durch
den Standard vorgegebenen Rahmen.

von bernd (Gast)


Lesenswert?

Das in Foren immer sofort gestritten werden muss kann ich echt nicht 
nachvollziehen, und einige scheinen Deutschlehrer zu sein. Dabei braucht 
man nachgewiesener Maßen nur Anfangs und Endbuchstaben eines Wortes um 
den Satz lesbar zu machen. Da finde ich es schwierieger sinnlos 
herunterzuscrollen um eine richtige Antwort zu finden.

Wer sich noch fürs Thema interessiert:
Keil Compiler 8051 und MPLap für Pics z.B. besitzen die #Bit und #Byte 
Befehle. Standar(d) hin oder her, es zählt was sich durchsetzt und 
sinnvoll ist. Und das ist struct bei bitfelder in keinster Weise, 
zumindest nicht bei 8Bit Prozessoren. Ob das Kernigham und Ritchi so 
wollten ist denen wahrscheinlich ebenso egal wie mir.

Die Frage steht also noch im Raum ob es eventuell duch eine .h eine 
bessere Lösung gibt die auch in AVR Studio debugged werden kann. bools 
mit endsprechende .h benutzen ja auch immer 1Byte.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

bernd wrote:

> Keil Compiler 8051 und MPLap für Pics z.B. besitzen die #Bit und #Byte
> Befehle. Standar(d) hin oder her, es zählt was sich durchsetzt und
> sinnvoll ist.

Und wer definiert, was sich ,,durchgesetzt'' hat?  Irgendwelche
mittelprächtigen Compiler?

Keil hat mich vor knapp 20 Jahren mal über einen Arbeitstag gekostet
um rauszufinden, dass sie in ihrer OS-9-Version für den m68k nicht
in der Lage waren, mit Variablen in geschachtelten Blöcken ordentlich
umzugehen (der Platz wurde nicht während des gesamten Funktionslaufs,
sondern erst am Beginn des Blocks auf dem Stack eingeräumt, dann aber
nie wieder ausgeräumt).  Irgendjemand bestätigte mir kürzlich, dass
dieses Problem immer noch existiere...

Durchgesetzt?  Durchgesetzt hat sich wohl ganz eindeutig GCC, und
IAR sicher auch.  Für Keil kenne ich außer Peter Dannegger (und von
mir aus dir) kaum einen, der sich über dessen Qualitäten begeistert
geäußert hätte, dafür aber genügend, die mir gesagt haben, dass sie
froh sind, dieses Teil dank GCC (und Wechsel von MCS51 weg) nicht
mehr benutzen zu müssen.  IAR hat zumindest insgesamt eine sehr gute
Reputation (und einen extremen Preis), und das interessanterweise,
obwohl er mit Erweiterungen wohl eher sparsam umgeht.

von bernd (Gast)


Lesenswert?

Ich habe nie behauptet das ich die Programmer unheimlich toll finde. Es 
ist die eine Funktion.
Ich muss Beruflich Pics, AVRs und Fujitsus Programmieren und mich 
zwangsläufig auch mit den Compilern auseinandersetzen. Dafor hatte ich 
es eben mit Keil und diverser damaligen "Puplic Domain" Software zu tun.
Alle hatten Qualitäten und Nachteile.

Das es AVR Studio nicht auf die Reihe bekommt beim watchen auch eine Bit 
Anzeige zu machen ist ein weiteres Manko.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

bernd wrote:

> Ich habe nie behauptet das ich die Programmer unheimlich toll finde.

(Programmer?  Oder Compiler?)

...aber bescheinigst ihnen, dass sich da irgendeine ihrer Erweiterungen
,,durchgesetzt'' hätte...

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.