2010-07-08 13 views
63

podając kod do obliczania wartości bezwzględnej liczby całkowitej (ABS) bez rozgałęzień od http://graphics.stanford.edu/~seander/bithacks.html:Co to jest CHAR_BIT?

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; 

Opatentowany odmiana:

r = (v^mask) - mask; 

Co jest CHAR_BIT i jak go używać?

+0

@ QuantumSoup Nie wiem, dlaczego pytasz, dlaczego chcesz robić hacki bitowe w Javie? Zrobiłbyś trochę hackowania w Javie, jeśli piszesz serwer gniazd w Javie i chcesz dekodować przychodzące pakiety udp przesyłające się w powietrzu z oprogramowania układowego, które wymaga nieco manipulacji. – JohnMerlino

Odpowiedz

0

Trzeba mieć świadomość, że ten kod zależy od zachowania realizację zdefiniowane prawego Bitshift na podpisanych typów. gcc obiecuje zawsze dawać rozsądne zachowanie (znak-bit-rozszerzenie), ale ISO C pozwala implementacji na wypełnianie zerami górnych bitów.

Jednym ze sposobów obejścia tego problemu:

#ifdef HAVE_SIGN_EXTENDING_BITSHIFT 
int const mask = v >> sizeof(int) * CHAR_BIT - 1; 
#else 
int const mask = -((unsigned)v >> sizeof(int) * CHAR_BIT - 1); 
#endif 

Twój Makefile lub config.h itd. Można określić HAVE_SIGN_EXTENDING_BITSHIFT w czasie kompilacji w zależności od platformy.

+0

lub możesz po prostu z 1 –

+79

Nie rozumiem, w jaki sposób może to być zaakceptowana odpowiedź, ponieważ nie odpowiada na pytanie, mimo że jest to bardzo interesujący komentarz. – qdii

+8

@Mauris: Ktoś edytował pytanie i promował pod-pytanie do tytułu pytania. Pierwotny tytuł był wprawdzie okropny, ale pytanie OP brzmiało o tym, jak działa cytowany kod hackowy, a "nie jest to, przynajmniej nie przenośne, a oto dlaczego" jest użyteczną odpowiedzią. –

159

CHAR_BIT to liczba bitów w char. Obecnie prawie wszystkie architektury używają 8 bitów na bajt, ale nie zawsze tak jest. Niektóre starsze maszyny miały 7-bitowy bajt ".

To można znaleźć w <limits.h>

+1

Niektóre procesory DSP mają 10 lub więcej bit-bajtów. –

+0

Mam test na moim komputerze i używa on 7-bitowego bajtu –

+47

C wymaga 'CHAR_BIT> = 8' i pozwala na znacznie większe wartości dla DSP, które mają tylko jeden typ rozmiaru, często 32-bitowy. POSIX wymaga 'CHAR_BIT == 8'. Ogólnie można założyć, że dowolna architektura wielozadaniowa/wielozadaniowa zorientowana na serwer lub interaktywna, z dowolną możliwością połączenia z Internetem lub wymiany danych tekstowych ze światem zewnętrznym ma wartość "CHAR_BIT == 8". –

1

Próbujesz odpowiedzieć na jednoznaczne pytanie (co to jest CHAR_BIT) oraz na ukryte pytanie (jak to działa) w pierwotnym pytaniu.


char w języku C i C++ stanowi najmniejszą jednostkę pamięci programu C może zająć *

CHAR_BIT w języku C i C++ oznacza liczbę bitów w Char. Musi być zawsze co najmniej 8 ze względu na inne wymagania dotyczące typu char. W praktyce na 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 lub sizeof, nie ma potrzeby, ponieważ wszystkie pierwotne typy w Javie mają stały rozmiar, a wewnętrzna struktura obiektów jest nieprzejrzysta dla programisty. W przypadku tłumaczenia tego kodu na język Java można po prostu zastąpić "sizeof (int) * CHAR_BIT - 1" stałą wartością 31.

W tym konkretnym kodzie jest on używany do obliczania liczby bitów w int. Należy pamiętać, że w tym obliczeniu zakłada się, że typ int nie zawiera żadnych bitów dopełniających.

Zakładając, że twój kompilator zdecyduje się na przedłużenie znaku na przesunięciach bitowych podpisanych cyfr i zakładając, że twój system używa 2s uzupełnienia dla liczb ujemnych, oznacza to, że "MASKA" będzie wynosić 0 dla wartości dodatniej lub zerowej, a -1 dla wartości ujemnej wartość.

Aby zanegować dwójkę liczby dopełnień, musimy wykonać bitowe nie, a następnie dodać. Równoważnie możemy odjąć jeden, a następnie bitowo go negować.

Ponownie zakładając dwójkę reprezentacji dopełnienia -1 jest reprezentowane przez wszystkie, więc wykluczenie lub z -1 jest równoznaczne z negacją bitową.

Tak więc, gdy v jest zerem, liczba jest pozostawiona w spokoju, gdy v to jedna, która jest zanegowana.

Należy pamiętać, że podpisane przepełnienie w C i C++ jest niezdefiniowanym zachowaniem. Tak więc użycie tego ABS wykonania na najbardziej ujemnej wartości prowadzi do nieokreślonego zachowania. Można to naprawić poprzez dodanie rzutów tak, że końcowa linia programu jest oceniana w unsigned int.

* Co zwykle jest, ale nie jest tak samo jak najmniejsza jednostka pamięci, którą sprzęt może rozwiązać. Implementacja może potencjalnie łączyć wiele jednostek pamięci adresowanej sprzętowo w jedną jednostkę pamięci programowalnej lub podzielić jedną jednostkę pamięci adresowej na wiele jednostek pamięci programowalnej.