Operatory bitowe zarządzają pojedynczymi bitami całkowitych typów liczbowych:
& — bitowe AND| — bitowe OR^ — bitowe XOR~ — bitowe NOT<< — przesunięcie w lewo>> — przesunięcie w prawoSzczególności:
int, unsigned int, itd.).signed) przy przesunięciach w prawo (>>) mogą generować przesunięcie arytmetyczne lub logiczne — zależy od kompilatora.unsigned, aby uniknąć rozszerzenia znaku.Przykład:
unsigned int flags = 0; flags |= 0x1; // Ustawia 0-ty bit flags &= ~0x2; // Resetuje 1-szy bit if ((flags & 0x4) != 0) { /* ... */ } // Sprawdza 2-gi bit
Czym różni się operacja przesunięcia w prawo (
>>) dla typówsigned intiunsigned int?
Często błędna odpowiedź: Uważa się, że przesunięcie w prawo zawsze wstawia zera z lewej strony, niezależnie od znaku.
Prawidłowa odpowiedź:
Dla typu unsigned int przesunięcie w prawo (>>) zawsze wstawia zera. Dla signed int wstawiane jest albo znak (jedynki, jeśli liczba jest ujemna), albo zera — zależy od implementacji kompilatora (architektura i zasady standardu C).
Przykład:
signed int a = -8; unsigned int b = (unsigned int)a; printf("%d ", a >> 1); printf("%u ", b >> 1);
W pierwszym przypadku wynik zależy od kompilatora; w drugim zawsze będzie to logiczne przesunięcie z zerami.
Historia
W kodzie obsługi protokołu flagi sygnałowe przechowywane były w typie char. Programista zastosował przesunięcie o 8 bitów (flag << 8), co z powodu przepełnienia i zasad podnoszenia typów doprowadziło do utraty wszystkich danych — result zawsze był równy zeru.
Historia
Odczyt danych z protokołu sieciowego (big-endian). Użycie operacji bitowych do łączenia bajtów nie było poprzedzone rzutowaniem na unsigned, co czasami prowadziło do nieoczekiwanych ujemnych wartości przy odczycie pola struktury.
Historia
Użycie ~ (bitowego NOT) do resetowania bitów w wartości typu int (np. ~0x80) było traktowane jako 0x7F, ale w rzeczywistości uzyskiwano liczbę ujemną -129, co prowadziło do błędów przy kolejnych obliczeniach i sprawdzeniach logicznych.