Forum: PC-Programmierung Bit-Manipulation in C (schnellere Formulierung?)


von Georg (Gast)


Lesenswert?

Hallo !

ich habe eine Frage zum Thema Bit-Manipulation in C
http://www.mikrocontroller.net/articles/Bitmanipulation#Standard_C_4

Abfrage 1 (verstanden und akzeptiert)
1
// prüfe ob Bit 4 in der Variable tmp gesetzt ist
2
if (tmp & 0x10) {
3
   // hier die Anweisungen, wenn das Bit gesetzt ist
4
}

Abfrage 2
1
// prüfe ob Bit 0 und Bit 4 in der Variable tmp gelöscht sind
2
// die Klammer ist wichtig!
3
if ((tmp & 0x11) == 0) {
4
   // hier die Anweisungen, wenn beide Bits gelöscht sind
5
}


Ich frage mich, ob
a) Abfrage 2, da länger als Abfrage 1, auch mehr Rechzeit benötigt.
b) man  Abfrage 2 nicht kürzer/schneller formulieren kann, sofern das
== 0 vermieden werden kann:

'tmp  &  0x11' sollte ja im Falle, dass Bit 0 und Bit 4 gelöscht
sind, einen Wert von 00000000 (also alles 0) zurückgeben.
Und   if   auf  00000000  angewandt  ergibt  FALSE,  sodass  man  doch
theoretisch nur ein Negation auf dieses FALSE anwenden müsste.

Wiederholung meines Operatoren-Verständnisses:

"Der bitweise Operator NOT (~) liest die Binärdaten der Ausdruckswerte 
und führt eine bitweise Negationsoperation durch.
Jede  Stelle,  für  die  im Ausdruck eine 1 steht, wird im Ergebnis zu
einer 0, und jede Stelle, für die im Ausdruck eine 0 steht, wird im 
Ergebnis zu einer 1. "

"In C, the ! (“logical NOT”) operator used on a value x evaluates to 0
when x is not 0, and 1 when x is 0."

Somit   müsste   doch   der  logische   NOT(!)  Operator  im folgenden
Ausdruck direkt auf den Boolschen  Wert  wirken (anstatt die einzelnen 
Bits des "tmp  &  0x11"
zu negieren):

geänderte Abfrage 2
1
// prüfe ob Bit 0 und Bit 4 in der Variable tmp gelöscht sind
2
// die Klammer ist wichtig!
3
if (!(tmp & 0x11)) {
4
   // hier die Anweisungen, wenn beide Bits gelöscht sind
5
}

Beweis:  Nur  wenn  tmp  &  0x11  == 0000000 wird der logisch negierte
Ausdruck TRUE (und tmp  &  0x11 wird nur 0000000, wenn Bit 0 und Bit 4
gelöscht sind)

Oder ist das falsch/nicht schneller?


Bzw. noch eine mögliche Form für Abfrage 2:
1
if (tmp & 0x11) {
2
   // leer
3
}
4
elseif {
5
   // hier die Anweisungen, wenn beide Bits gelöscht sind
6
}


Für  Korrektnis-, Performance-  oder allgemeine Hinweise bin ich
sehr dankbar :)

Georg

von Novice (Gast)


Lesenswert?

Du kannst das auch selbst prüfen: jags durch einen Compiler und schau 
dir den generierten Code an.

von Matthias L. (Gast)


Lesenswert?

>if (tmp & 0x10)
>if ((tmp & 0x11) == 0)


Es braucht beides gleich lange. Denn ersteres if kann man auch so 
schreiben:
>if ( (tmp & 0x10) != 0 )
>if ( (tmp & 0x11) == 0 )


Das Ergebnis auf asm-Ebene ist immer dasselbe:
Ein and-Verknüpfung mit einer Konstante (einmal 0x10 und einmal 0x11), 
und anschliessen wird auf Null (branch if zero) oder verschieden null 
(branch if not zero) getestet...

von Georg (Gast)


Lesenswert?

alles klar, vielen Dank! :)
ein beruhigendes Gefühl wenn das Gefühl/Gelernte einem nicht im Stich 
lässt *g Georg

von Dirk B. (dirkb2)


Lesenswert?

Vertrau der Macht des Compilers,  Georg!

Der macht viele Ausdrücke besser wenn er darf.
Schreib es so hin, dass du (und auch andere) es noch in vier Wochen 
verstehen kanst.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Negationen in If-Bedingungen kosten normalerweise keine zuätzliche Zeit,
da bei praktisch allen Prozessoren (insbesondere auch denen, die in PCs
verbaut sind) alle bedingten Sprungbefehle sowohl in direkter als auch
negierter Form vorhanden sind.

Einen Unterschied gibt es höchstens dadurch, dass im ersten Fall 1 Bit
und im zweiten Fall 2 Bits abgefragt werden. Manche Prozessoren haben
spezielle Befehle zur Einzelbitabfrage. So würde bspw. auf einem AVR die
erste Abfrage in vielen Fällen einen Taktzyklus schneller laufen als die
zweite. Bemerkbar macht sich dieser Unterschied aber nur dann, wenn das
Programm fast ausschließlich aus solchen Abfragen besteht.

PC-Prozessoren haben diese Spezialbefehle wohl nicht. Zumindest hat sie
der GCC in einem gerade durchgeführten Test nicht generiert. Der
generierte Code ist in beiden Fällen exakt nach dem gleichen Schema
aufgebaut, so dass sich kein Laufzeitunterschied ergibt.

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.