Cytując kod do obliczenia całkowitej wartości bezwzględnej (abs) bez rozgałęziania z http://graphics.stanford.edu/~seander/bithacks.html :
int v; // we want to find the absolute value of v
unsigned int r; // the result goes here
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
r = (v + mask) ^ mask;
Opatentowana odmiana:
r = (v ^ mask) - mask;
Co to jest CHAR_BIT
i jak z niego korzystać?
c
bit-manipulation
dato datuashvili
źródło
źródło
CHAR_BIT
?” , nawet jeśli nie było to pierwotne pytanie. :( Biorąc pod uwagę twoje wyjaśnienie, rozumiem, dlaczego napisałeś tę odpowiedź, ale dla potomnych może być bardziej przydatne albo (a) usunięcie odpowiedzi i przepisanie jej jako komentarz do pytania, tak aby @ AraK pojawił się na górze, albo (b) zredaguj swoją odpowiedź tak, aby odpowiadała aktualnemu tytułowi pytaniaCHAR_BIT
jest liczbą bitów wchar
. Obecnie prawie wszystkie architektury używają 8 bitów na bajt, ale nie zawsze tak jest. Niektóre starsze maszyny miały 7-bitowe bajty.Można go znaleźć w
<limits.h>
.źródło
CHAR_BIT>=8
i dopuszcza znacznie większe wartości dla DSP, które mają tylko jeden rozmiar typu, często 32-bitowy. POSIX wymagaCHAR_BIT==8
. Ogólnie rzecz biorąc, można założyć, że każda architektura zorientowana na serwer lub zorientowana na interaktywne użytkowanie dla wielu użytkowników / wielozadaniowości z możliwością podłączenia do Internetu lub wymiany danych tekstowych ze światem zewnętrznymCHAR_BIT==8
.int8_t
iuint8_t
istnienia. Tak więc istnieje typ szerokości 8. Ponieważsizeof
każdy typ musi być zgodny z, wsizeof char
rzeczywistościsizeof int8_t
musi wynosić 1. WięcCHAR_BIT == 8
. Pisałem coś wokół tego obeservation tutaj: gustedt.wordpress.com/2010/06/01/how-many-bits-has-a-bytestdint.h
. Tak więc jest to wymagane i jest również oznaczone jako rozszerzenie standardu ISO C , bez odwoływania się do konkretnej wersji tej normy. Mój błąd.Próbuje odpowiedzieć zarówno na pytanie jawne (co to jest CHAR_BIT), jak i na niejawne (jak to działa) w pierwotnym pytaniu.
Znak w C i C ++ reprezentuje najmniejszą jednostkę pamięci, do której program C może adresować *
CHAR_BIT w C i C ++ reprezentuje liczbę bitów w znaku. Zawsze musi wynosić co najmniej 8 ze względu na inne wymagania dotyczące typu znaku. W praktyce we wszystkich nowoczesnych komputerach ogólnego przeznaczenia wynosi dokładnie 8, ale niektóre systemy historyczne lub specjalistyczne mogą mieć wyższe wartości.
Java nie ma odpowiednika CHAR_BIT ani sizeof, nie ma takiej potrzeby, ponieważ wszystkie typy pierwotne w Javie mają stały rozmiar, a wewnętrzna struktura obiektów jest nieprzejrzysta dla programisty. Jeśli tłumaczysz ten kod na Javę, możesz po prostu zamienić „sizeof (int) * CHAR_BIT - 1” na stałą wartość 31.
W tym konkretnym kodzie jest używany do obliczenia liczby bitów w int. Należy pamiętać, że to obliczenie zakłada, że typ int nie zawiera żadnych bitów wypełniających.
Zakładając, że twój kompilator zdecyduje się na rozszerzenie ze znakiem na przesunięciach bitowych liczb ze znakiem i zakładając, że twój system używa reprezentacji dopełnienia 2s dla liczb ujemnych, oznacza to, że "MASKA" będzie równe 0 dla wartości dodatniej lub zerowej i -1 dla wartości ujemnej.
Aby zanegować liczbę uzupełnienia do dwójek, musimy wykonać bitowe nie, a następnie dodać jeden. Równocześnie możemy odjąć jeden, a następnie zanegować bitowo.
Ponownie zakładając, że reprezentacja dopełnienia dwójki -1 jest reprezentowana przez wszystkie jedynki, więc wyłączność lub z -1 jest równoważne negacji bitowej.
Więc kiedy v jest równe zero, liczba jest pozostawiana sama, gdy v wynosi jeden, jest negowana.
Należy być świadomym tego, że przepełnienie podpisu w C i C ++ jest niezdefiniowanym zachowaniem. Tak więc użycie tej implementacji ABS na najbardziej ujemnej wartości prowadzi do nieokreślonego zachowania. Można to naprawić, dodając rzutowania, tak aby ostatnia linia programu była oceniana w unsigned int.
* Która zwykle, ale nie zawsze jest taka sama, jak najmniejsza jednostka pamięci, którą sprzęt może adresować. Implementacja może potencjalnie łączyć wiele jednostek pamięci adresowalnej sprzętowo w jedną jednostkę pamięci adresowalnej programowo lub podzielić jedną jednostkę pamięci adresowalnej sprzętowo na wiele jednostek pamięci adresowalnej programowo.
źródło