Forum: Mikrocontroller und Digitale Elektronik Daten eines Bitfeldes via for/Next nutzen


von ennen (Gast)


Lesenswert?

Hallo.

Ich würde gerne mit einer For/Next Schleife auf ein Bitfeld zugreifen 
und weiß grade nicht wie ich dies in dieser Situation machen soll.

Bitfeld:
1
uint8_t testdata[10] = {1};
2
3
struct data
4
  {
5
    uint8_t bit1: 1;
6
    uint8_t bit2: 1;
7
    uint8_t bit3: 1;
8
    uint8_t bit4: 1;
9
    uint8_t bit5: 1;
10
    uint8_t bit6: 1;
11
    uint8_t bit7: 1;
12
    uint8_t bit8: 1;
13
    uint8_t bit9: 1;
14
    uint8_t bit10: 1;
15
  } ReceiveBuffer;

nun möchte ich z.B. ein Array oder was auch immer in diese Struktur 
kopieren:
1
for (i=0;i<10;i++)
2
{
3
    ReceiveBuffer.bit & i = testdata[i];
4
}

Mit dem  "*.bit & i" soll nur verdeutlichen wo gerade mein Problem ist 
;)
Dass der Syntax nicht stimmt ist ja logisch...

Ich dachte zuerst ich kopiere an die Struct-Adresse + i eine 1 oder 0, 
aber laut Doku wird das Struct ja im Speicherbereich nicht zwingend 
hintereinander angelegt.

Wie muss ich das denn schreiben, dass ich es nutzen kann?
Oder gibt es hier gar keine Lösung?

Danke fürs überlegen und nun erst einmal gute Nacht!

von Harald N. (haraldn)


Lesenswert?

Bin kein C Profi aber warum nicht die Bit-Struct und das Array in eine 
Union? Würde dann auch nicht doppelt so viel Speicher brauchen und das 
Kopieren wäre hinfällig.

von Daniel A. (daniel-a)


Lesenswert?

Verwende niemals Bitfields! Auch wenn man damit etwas Platzsparen kann, 
bool ist meistens schneller. Bitfields sind zum Aufbereiten Empfangener 
Daten sowie dem Speichern derselben ungeeignet. Man kann sich über die 
Reihenfolge von Bitferldern nie Sicher sein. Ich empfehle sowas:

Ungetestet:
1
#define DEC_BITS(T,ID,N) T ID[((N)+sizeof(T)*8-1)/sizeof(T)/8]
2
#define GET_BIT(ID,I) (((unsigned char*)(ID))[(I)/8]&(1<<((I)&7)))
3
#define SET_BIT(ID,I) (((unsigned char*)(ID))[(I)/8]|=(1<<((I)&7)))
4
#define UNSET_BIT(ID,I) (((unsigned char*)(ID))[(I)/8]&=(1<<((I)&7)))
5
#define SET_BIT_TO(ID,I,X) ((void)((X)?SET_BIT(ID,I):UNSET_BIT(ID,I)),(X))
6
7
struct data {
8
  DEC_BITS(uint8_t,bit,10);
9
} ReceiveBuffer;
1
for(i=0;i<10;i++){
2
  (void)SET_BIT_TO(ReceiveBuffer.bit,i,testdata[i]);
3
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Daniel A. schrieb:
> Man kann sich über die Reihenfolge von Bitferldern nie Sicher sein.

Was verleitet Dich zu dieser Annahme?

von Matz K. (xt-matz)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Daniel A. schrieb:
>> Man kann sich über die Reihenfolge von Bitferldern nie Sicher sein.
>
> Was verleitet Dich zu dieser Annahme?

Ich kann das nur mit K&R bestätigen. Unter anderem schreiben die beiden:
1
Almost everything about fields is implementation-dependent. 
2
Whether a field may overlap a word boundary is implementation-defined...
3
Fields are assigned left to right on some machines and right to left on others. 
4
This means that although fields are useful for maintaining internally-defined 
5
data structures, the question of which end comes first has to be carefully
6
considered when picking apart externally-defined data; 
7
programs that depend on such things are not portable.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Vergiß Bitfelder, das mögen CPUs nicht.
1
uint16_t ReceiveBuffer;
2
uint16_t val = 0;
3
for ( uint8_t i=0;i<10;i++)
4
{
5
  val <<= 1;
6
  if( testdata[i] )
7
    val |= 1;
8
}
9
ReceiveBuffer = val;

von ennen (Gast)


Lesenswert?

Hi da.

Vielen Dank für die Tips!

Werde das Ganze dann doch mit einer Variable und Bitmanipulation regeln.
Schade, die Struktur hätte man schön im Debugger ansehen können.
Leider kann das AtmelStudio ja nur DEZ und HEX als Anzeige.

Schönes Wochenende!

von Hans Ulli K. (Gast)


Lesenswert?

Daniel A. schrieb:
> Verwende niemals Bitfields! Auch wenn man damit etwas Platzsparen kann,
> bool ist meistens schneller. Bitfields sind zum Aufbereiten Empfangener
> Daten sowie dem Speichern derselben ungeeignet. Man kann sich über die
> Reihenfolge von Bitferldern nie Sicher sein. Ich empfehle sowas:

irgendwie verwechselst du was ...

Das mit der Reihenfolge ist wegen Little/Big Endian.
Und bei ARM gibt es effiziente Befehle zum setzen/löschen/abfragen von 
Bits.

von Daniel A. (daniel-a)


Lesenswert?

Hans Ulli Kroll schrieb:
> Daniel A. schrieb:
>> Verwende niemals Bitfields! Auch wenn man damit etwas Platzsparen kann,
>> bool ist meistens schneller. Bitfields sind zum Aufbereiten Empfangener
>> Daten sowie dem Speichern derselben ungeeignet. Man kann sich über die
>> Reihenfolge von Bitferldern nie Sicher sein. Ich empfehle sowas:
>
> irgendwie verwechselst du was ...
>
> Das mit der Reihenfolge ist wegen Little/Big Endian.

Das wurde hier bereits ausgibig besprochen:
Beitrag "Re: rechnet der preprocessor in C gcc (AVR) multiplikation aus?"
Bitordering wird nur von ABI definiert. Ich sage das nur deshalb so 
dramatisch, damit niemand auf die Idee kommt meinen Fehler zu 
wiederholen und bitfelder zum Parsen, Speichern, etc. von Daten 
verwendet. Eine andere Platform, oder ein ABI change mit einer neuen 
Compilerversion, und die Reihenfolge kann schonwieder ganz anders 
Aussehen.


> Und bei ARM gibt es effiziente Befehle zum setzen/löschen/abfragen von
> Bits.

Das mag sein, aber um diese zu nutzen ist man ja nicht zwangslaufig auf 
Bitfields angewiesen. Ich habe noch nie einen fall gesehen, in welchem 
diese einen echten Vorteil bieten. Natürlich gibt es Spezialfälle, in 
welchen diese sinvoll sind, aber die sind sehr selten.

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.