Bei der Programmierung von Microcontrollern und beim Steuern von elektronischen Schaltungen muss man sehr häufig bestimmte Bits setzen, löschen oder auslesen. Hier finden sich die Grundlagen, wie man das in C machen kann.
if ((variable & bitmaske) == bitmaske)
testet, ob alle in der Bitmaske angegebenen Bits gesetzt sind. Falls man nur prüfen will, ob irgendwelche Bits der Maske gesetzt sind, reicht:
if (variable & bitmaske)
variable |= bitmaske;
Bedarf wohl keiner weiteren Erklärung
variable &= ~(bitmaske);
ebenfalls einfache boolsche Algebra, nicht vergessen die Maske zu invertieren.
Mittels des XOR-Operators können einzelne oder mehrere Bits invertiert werden:
variable ^= (bitmaske);
Mit << kann man Bits nach links schieben, z.B. wird mit "1<<4" die 1 um vier Stellen nach links geschoben - ergibt also den Wert 16.
Ebenso kann man mit >> Bits nach rechts schieben.
Hierbei gibt es aber bei grösseren Datentypen eine Stolperfalle: Die "1" wird vom Compiler als Typ "Integer" angesehen. Zum Beispiel beim AVR-GCC ist Integer aber nur 16 Bit, wenn man den shift Operator nun auf eine 32-Bit Variable anwendet, geht das schief. So löst man das dann korrekt:
int32_t reg_32;
uint64_t reg_64;
reg_32 |= ((uint32_t)1 << 23); /* Setze Bit 23 */
reg_32 |= (1L << 23); /* kürzere Schreibweise */
reg_64 |= (1LL << 51); /* Setze Bit 51 */
Wenn man so verzweifelt um Speicher ringt, dass man sich keine Hilfsvariablen
mehr erlauben kann, ist meist ohnehin Assembler angesagt.
Da Assembler aber Prozessorspezifisch ist, möchte ich das Prinzip hier in C
zeigen. Die verwendete Prozessorarchitektur muss XOR auf die Zielwerte
anwenden können, um eine echte Ersparnis zu erhalten (wenn die Werte erst
in Register kopiert werden müssen, kann man gleich ein Register als
Hilfsvariable nehmen).
void xchng(uint8_t *r0, uint8_t *r1)
{
*r0 ^= *r1;
*r1 ^= *r0;
*r0 ^= *r1;
}