Bit-Manipulation in C (schnellere Formulierung?)

Gast #3673244
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
Gast #3673290
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...
Moderator #3673356
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren