Forum: Compiler & IDEs Bit Position für Array verwenden


von Simon (Gast)


Lesenswert?

Kann man diesen code nicht irgendwie schöner zusammen fassen?

changed beinhaltet einzelne bits und ich frage quasi ab an welcher 
Position
diese sich befinden.
1
0b00000001 = 0x01 = Bit 0 ist gesetzt = val_digital[0]
2
0b00000010 = 0x02 = Bit 1 ist gesetzt = val_digital[1]
3
...

Gibt es hier eine elegantere Lösung als das einzelnd aufzählen zu 
müssen?
1
   if (changed & 0x01) digital[0].value += 1;
2
   if (changed & 0x02) digital[1].value += 1;
3
   if (changed & 0x04) digital[2].value += 1;
4
   if (changed & 0x08) digital[3].value += 1;
5
   if (changed & 0x10) digital[4].value += 1;
6
   if (changed & 0x20) digital[5].value += 1;
7
   if (changed & 0x40) digital[6].value += 1;
8
   if (changed & 0x80) digital[7].value += 1;

von Yalu X. (yalu) (Moderator)


Lesenswert?

Du kannst das Ganze in eine Schleife packen. Dadurch wird es im 
Quellcode schöner aber evtl. auch etwas langsamer.

von Simon (Gast)


Lesenswert?

genau das mit der Schleife habe ich vor, nur das setzt irgendwie voraus 
das
ich x in

digital[x].value += 1;

errechnen kann und zwar anhand des bits in changed.

bzw eigentlich andersrum.

for (x=0; x<8; x++) {
 if (changed & 0x20) digital[x].value += 1;
}

Nur hier hab ich ebend genau das problem dies Bit zu erechnen

von Karl H. (kbuchegg)


Lesenswert?

Simon schrieb:

> errechnen kann und zwar anhand des bits in changed.

Na ja.
Das ist ja nicht weiter schwer.
Die Verundung mit einem Maskenwert bleibt weiterhin.
Einziger UNterschied.
Bisher waren deine Maskenwerte 0x01, 0x02, 0x04, 0x08, ....
WEnn man sich die aber mal auf Bitebene ansieht, dann sieht man, dass 
das im Grunde ja immer nur ein einzige 1 Bit ist, welches in jeder 
weiteren Maskenstufe um 1 Position nach links rutscht.
1
Bei x gleich 0     0x01       00000001
2
Bei x gleich 1     0x02       00000010
3
Bei x gleich 2     0x04       00000100
4
Bei x gleich 3     0x08       00001000
5
...

Diese 'weiterrutschen' kann man natürlich auch programmierern.
1
  uint8_t mask = 0x01;
2
3
  for (x=0; x<8; x++) {
4
    if (changed & mask)
5
      digital[x].value += 1;
6
    mask = mask << 1;
7
  }


PS: Bitte vergiss mein voriges Posting wieder - ich habs bereits 
gelöscht. Das war Blödsinn und ist so in deinem konkreten Fall nicht 
anwendbar.

: Bearbeitet durch User
von Simon (Gast)


Lesenswert?

Vielen Dank für deine Antwort.

ok... das wird funktionieren,
aber habe ich damit wirklich irgendwas gewonnen?

Ich meine der code ist nicht einfacher geworden und vermutlich auch 
nicht
schneller. Fazit.. ich lasse es wie es ist?

von Karl H. (kbuchegg)


Lesenswert?

Simon schrieb:
> Vielen Dank für deine Antwort.
>
> ok... das wird funktionieren,
> aber habe ich damit wirklich irgendwas gewonnen?
>
> Ich meine der code ist nicht einfacher geworden und vermutlich auch
> nicht
> schneller.

Das ist schwer zu sagen.
Im Zweifelsfall musst du es kompilieren und dir das Ergebnis auf 
Assembler-Ebene ansehen.
Kürzer ist er auf Assembler-ebene schon - würde ich mal sagen.
Obs auch schneller ist, ist eine andere Frage.

von Axel Z. (axel_z)


Lesenswert?

Noch sparender geht es wohl so:
1
digital[0].value += changed & 1; changed>>=1;
2
digital[1].value += changed & 1; changed>>=1;
3
digital[2].value += changed & 1; changed>>=1;
4
digital[3].value += changed & 1; changed>>=1;
5
digital[4].value += changed & 1; changed>>=1;
6
digital[5].value += changed & 1; changed>>=1;
7
digital[6].value += changed & 1; changed>>=1;
8
digital[7].value += changed & 1;

oder als schleife
1
uint8_t i;
2
for (i=0; i<8; ++i){
3
  digital[i].value += changed & 1;
4
  changed>>=1;
5
}

Gruß

von Simon (Gast)


Lesenswert?

Vielen Dank für beide Beispiele!

Man merkt aber auch schon das es dann immer
schwerer wird den code zu lesen und zu verstehen :-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Simon schrieb:
> Gibt es hier eine elegantere Lösung als das einzelnd aufzählen zu
> müssen?

Mit GCC:

digital[0].value += __builtin_popcount (changed);

http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

Je nach Target ist das in Assembler imlementiert, z.B. für die aktuellen 
Versionen von avr-gcc (ab 4.7).

: Bearbeitet durch User
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.