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.