Poniższa funkcja może zrobić to, czego potrzebujesz:
int isNthBitSet (unsigned char c, int n) {
static unsigned char mask[] = {128, 64, 32, 16, 8, 4, 2, 1};
return ((c & mask[n]) != 0);
}
Zakłada 8-bitowych bajtów (nie podano w C) i nieco zerowego jest najwyższy order jeden. Jeśli te założenia są niepoprawne, po prostu sprowadza się do rozszerzenia i/lub ponownego uporządkowania tablicy mask
.
Nie należy sprawdzać błędów, ponieważ jako najważniejszą uwagę podano prędkość. Czy nie przekazać nieprawidłowy n
, które będzie niezdefiniowane zachowanie.
Na insane poziom optymalizacji -O3
, gcc daje nam:
isNthBitSet: pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
movzbl 8(%ebp), %edx
popl %ebp
testb %dl, mask(%eax)
setne %al
movzbl %al, %eax
ret
mask: .byte -128, 64, 32, 16, 8, 4, 2, 1
który jest dość mały i wydajny. A jeśli uczynisz to statycznym i zaproponujesz inlining lub wymusisz inline jako definicję makra, możesz nawet ominąć koszt wywołania funkcji.
Po prostu upewnij się, że porównujesz wszystkie dostępne rozwiązania, w tym jeden: (a). Najlepsza mantra w optymalizacji to "Zmierz się, nie zgaduj!"
Jeśli chcesz wiedzieć, jak działają operatory bitowe, zobacz here. Uproszczona wersja tylko AND jest poniżej.
Operacja I &
ustawi bit w celu tylko wtedy, gdy oba bity zostaną ustawione w tych źródłach. Odpowiednia tabela:
AND | 0 1
----+----
0 | 0 0
1 | 0 1
Dla danej wartości char
używamy maski single-Bit, by sprawdzić, czy bit jest ustawiony. Powiedzmy, że masz wartość 13 i chcesz sprawdzić, czy ustawiony jest trzeci od najmniej znaczącego bitu.
Decimal Binary
13 0000 1101
4 0000 0100 (the bitmask for the third-from-least bit).
=========
0000 0100 (the result of the AND operation).
Można zobaczyć, że wszystkie bity zerowe w masce powodują, że równoważne bity wynikowe wynoszą zero. Pojedynczy bit w masce zasadniczo pozwoli bitu ekwiwalentnemu w przepływie wartości przejść do wyniku. Wynik jest wtedy zerowy, jeśli bit, który sprawdzamy, był równy zeru lub niezerowy, jeśli był jeden.
To stąd pochodzi wyrażenie w instrukcji return
. Wartości w tabeli przeglądowej mask
są wszystkie maski single-bitowe:
Decimal Binary
128 1000 0000
64 0100 0000
32 0010 0000
16 0001 0000
8 0000 1000
4 0000 0100
2 0000 0010
1 0000 0001
(a) wiem jak dobry jestem, ale nie :-)
Duplikat, http://stackoverflow.com/questions/523724/cc-check-if-one-bit-is -set-in-ie-int-variable – blueshift
To nie jest dupe, szczególnie pytano o metody ** non-bitshift **. – paxdiablo