Forum: Mikrocontroller und Digitale Elektronik Welchen Code würdet ihr bevorzugen


von misra ten (Gast)


Lesenswert?

Hallo :)

zum maskieren bzw. Löschen eines Bits im Byte
schwanke ich zwischen
1
variable &= ~ (1 << i);

und
1
code U8 demask[8] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F };
2
variable &= demask [i];

ersteres ist vermutlich schneller
aber letzteres uu besser lesbar

was meint ihr?

von dave (Gast)


Lesenswert?

1., das andere ist eine verschwendung von 8 byte, völlig unnötig

von PittyJ (Gast)


Lesenswert?

Über sowas mache ich mir keine Gedanken. Da gibt es wichtigeres.

von asdf (Gast)


Lesenswert?

Ich mache es am liebsten so:
1
variable &= 0b11101110;
Ist übersichtlich und es lassen sich auch sehr einfach mehrere Bit 
löschen.

von Vlad T. (vlad_tepesch)


Lesenswert?

hauptfrage: welche MCU
Ein AVR hat keinen Barrelshifter, da ist variables Shiften mit einer 
Zählschleife verbunden (und braucht möglicherweise ebenfalls 8 Byte)

von Ben _. (burning_silicon)


Lesenswert?

Ersteres dürfte auch schneller sein. Das zweite wird der Compiler mit 
etwas Pech zu einem riesigen Ballast aufblasen.

von misra ten (Gast)


Lesenswert?

@Vlad: 8051

von Karl H. (kbuchegg)


Lesenswert?

misra ten schrieb:
> Hallo :)
>
> zum maskieren bzw. Löschen eines Bits im Byte
> schwanke ich zwischen

in welchem Zusammenhang?

Sehr oft lässt sich die Operation

>
1
> variable &= ~ (1 << i);
2
>

in einer Schleife durch eine geeignete Umstrukturierung auf eine 
Maskierung mit einer Konstanten anstatt einem variablen i umformen.

> aber letzteres uu besser lesbar

Das ist kein Argument.
Denn
1
#define CLEAR_BIT(v,i)   (v) &= ~(1<<i)
2
3
4
int main()
5
{
6
   CLEAR_BIT( vairable, i );
7
}

ist noch besser lesbar, als deine beiden Varianten.
Code kann man sich immer so zurecht legen, dass er lesbar ist.

von Vlad T. (vlad_tepesch)


Lesenswert?

Karl Heinz Buchegger schrieb:
> #define CLEAR_BIT(v,i)   (v) &= ~(1<<i)

wenn dann bitte:
#define CLEAR_BIT(v,i)   ((v) &= ~(1<<(i)))

von Bernd N (Gast)


Lesenswert?

8051 ist BIT Adressierbar.

von Ben _. (burning_silicon)


Lesenswert?

In Assembler wäre das sooo schön einfach...

ANDI R16,0b11111110

Genau einen Takt später ist das letzte Bit gelöscht.

von Christian B. (casandro)


Lesenswert?

Undokumentierte Tabellen sind meistens schlecht. Somit würde ich beim 
Beispiel mit dem Verschieben bleiben. Das kann der Compiler auch 
optimieren. Mit der Tabelle erzwingst Du Speicherzugriffe.

von Karl H. (kbuchegg)


Lesenswert?

Ben _ schrieb:
> In Assembler wäre das sooo schön einfach...

Sieh dir noch mal die Ausgangssituation an.
i ist eine Variable.

Wenn dein µC keinen Barrelshifter hat, ist es vorbei mit 'so schön 
einfach'.

von Ben _. (burning_silicon)


Lesenswert?

Verstehe ich möglicherweise nicht. Die Variable sieht aus wie ein 
einfacher 8-Bit-Wert (byte). Wenn ich den in R16 oder sonstwohin lade wo 
ich ANDI anwenden kann, kann ich den doch damit verarzten und gut...?

von Sven B. (scummos)


Lesenswert?

asdf schrieb:
> Ich mache es am liebsten so:
>
1
> variable &= 0b11101110;
2
>
> Ist übersichtlich und es lassen sich auch sehr einfach mehrere Bit
> löschen.

Das finde ich auch sehr schön, ist halt kein Standard-C. Aber wen 
kümmert's.
Ansonsten wirkt ein Kommentar oder eine gut benannte Inline-Funktion 
auch Wunder. Oder, wie schon erwähnt, ein Makro tut's auch.

von Karl H. (kbuchegg)


Lesenswert?

Ben _ schrieb:
> Verstehe ich möglicherweise nicht. Die Variable sieht aus wie ein
> einfacher 8-Bit-Wert (byte). Wenn ich den in R16 oder sonstwohin lade wo
> ich ANDI anwenden kann

Das I in ANDI ist schon ein deutlicher Hinweis darauf, dass du damit ein 
Register nur mit einer Konstantem verunden kannst.

   1<<i
ist aber keine Konstante, wenn i eine Variable ist.


variable &= ~ (1 << i);

  wenn i gerade den Wert 0 hat, dann wird das 0-te Bit gelöscht
  wenn i gerade den Wert 1 hat, dann wird das 1-te Bit gelöscht
  wenn i gerade den Wert 2 hat, dann wird das 2-te Bit gelöscht
  ....

Preisfrage:
Welches Bit (Bitnummer) wird denn in
1
utin8_t var;
2
3
void foo( uint8_t i )
4
{
5
  var &= ~( 1<<i );
6
}
gelöscht? Wie soll (kann, muss) dann deiner Ansicht nach die ANDI 
Instruktion dafür aussehen, die genau diesen Funktionskörper 
implementiert? Der Einfachheit halber kannst du davon ausgehen, dass der 
Inhalt von var schon in R16 liegt. Es geht nur um das ANDI.
Wenn du mal versuchst, genau diese Funktion in Assembler zu 
programmieren, kommst du drauf, dass dir nichts anderes übrig bleibt, 
als eine Schleife zu konstruieren, mit der du dir erst mal das 0-Bit an 
die richtige Stelle verschiebst um so die Maske zu erzeugen, die dann 
anschliessend verundet werden kann.

von Ben _. (burning_silicon)


Lesenswert?

Der µC sollte auch ein indirektes AND können... Der immediate-Wert war 
nur weil ich dachte, es geht NUR um das letzte Bit.

von Karl H. (kbuchegg)


Lesenswert?

Ben _ schrieb:
> Der µC sollte auch ein indirektes AND können...

indirekt ist was anderes.

Es reicht, wenn er einen Barrelshifter hätte.
Hat dieser µC aber nicht.

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.