Potrzebujesz pomocy w zrozumieniu metody "getbits ()" w rozdziale 2 K & R C
W rozdziale 2, sekcja o operatorach bitowych (sekcja 2.9), mam problem ze zrozumieniem, jak działa jedna z przykładowych metod.
Oto metoda:
unsigned int getbits(unsigned int x, int p, int n) {
return (x >> (p + 1 - n)) & ~(~0 << n);
}
Idea jest taka, że dla podanej liczby x , zwróci Nbity zaczynające się od pozycji p, licząc od prawej (z najdalszym prawym bitem będącym pozycją 0). Biorąc pod uwagę następującą metodę main()
:
int main(void) {
int x = 0xF994, p = 4, n = 3;
int z = getbits(x, p, n);
printf("getbits(%u (%x), %d, %d) = %u (%X)\n", x, x, p, n, z, z);
return 0;
}
Wyjście to:
getbits(63892 (f994), 4, 3) = 5 (5)
Dostaję porcje tego, ale mam problemy z" dużym obrazem", głównie z powodu bitów (nie zamierzony kalambur), których nie rozumiem.
Część, z którą mam szczególne problemy, to element uzupełniający: ~(~0 << n)
. Myślę, że dostaję pierwszą część, zajmującą się x ; to ta część (a potem maska), z którą zmagam się -- i jak to wszystko łączy się, aby faktycznie odzyskać te bity. (Co zweryfikowałem, zarówno kodem jak i Sprawdzam wyniki za pomocą calc.exe -- dzięki Bogu ma widok binarny!)
6 answers
Użyjmy 16 bitów dla naszego przykładu. W takim przypadku ~0 jest równe
1111111111111111
Kiedy przesuniemy w lewo to n
bity (3 w Twoim przypadku), otrzymujemy:
1111111111111000
Ponieważ 1
s po lewej są odrzucane, a 0
S są podawane po prawej. Następnie ponowne dopełnienie daje:
0000000000000111
Więc jest to po prostu sprytny sposób, aby uzyskać n
1-bity w najmniej znaczącej części liczby.
"x bit", który opisujesz, przesunął podaną liczbę (f994) na tyle daleko, że najmniej znaczące 3 bity to te, które chcesz. W tym przykładzie bity, o które prosisz, są otoczone przez '.'postacie.
ff94 11111111100.101.00 # original number
>> p+1-n [2] 0011111111100.101. # shift desired bits to right
& ~(~0 << n) [7] 0000000000000.101. # clear all the other (left) bits
I tu masz swoje kawałki. Ta da !!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-05 13:03:38
Powiedziałbym, że najlepszą rzeczą do zrobienia jest zrobić problem ręcznie, w ten sposób zrozumiesz, jak to działa.
Oto co zrobiłem używając 8-bitowej niepodpisanej liczby całkowitej.
Nasza liczba to 75 chcemy 4 bity zaczynając od pozycji 6. wywołaniem funkcji będzie getbits(75,6,4);
75 W binarnym jest 0100 1011
Tworzymy więc maskę o długości 4 bitów, zaczynając od bitu najniższego rzędu.
~0 = 1111 1111
~ = 0000 1111
- Teraz wypychamy bity, które chcemy z liczby do bitów najniższego rzędu, aby zmieniamy binarne 75 o 6+1-4=3.
0100 1011 >>3 0000 1001
Teraz mamy maskę prawidłowej liczby bitów w niskiej kolejności i bitów, które chcemy z oryginalnej liczby w niskiej kolejności.
- so we & them
0000 1001
& 0000 1111 ============ 0000 1001
Więc odpowiedź jest dziesiętna 9.
Uwaga: wyższość rzędu to po prostu wszystkie zera, co czyni maskowanie zbędnym w tym przypadku, ale mogło to być cokolwiek w zależności od wartości liczby, od której zaczęliśmy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-13 15:31:35
~(~0 << n)
tworzy maskę, która będzie miała włączone n
prawo-większość bitów.
0
0000000000000000
~0
1111111111111111
~0 << 4
1111111111110000
~(~0 << 4)
0000000000001111
I dodanie do wyniku czegoś innego zwróci to, co jest w tych n
bitach.
Edit: chciałem zwrócić uwagę na kalkulator programisty, którego używam od zawsze: AnalogX PCalc.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-01 23:29:25
Nikt jeszcze o tym nie wspomniał, ale w ANSI C ~0 << n
powoduje nieokreślone zachowanie.
Dzieje się tak dlatego, że ~0
jest liczbą ujemną, a liczba ujemna przesunięta w lewo jest niezdefiniowana.
Reference: C11 6.5.7 / 4 (wcześniejsze wersje miały podobny tekst)
Wynikiem
E1 << E2
jestE1
przesunięte w lewoE2
pozycje bitowe; puste bity są wypełnione zerami. [...] Jeżeli E1 ma podpis typ i wartość nonnegatywna orazE1
×2
E2
jest reprezentowalny w wyniku Typ, wtedy jest to wartość wynikowa; w przeciwnym razie zachowanie jest niezdefiniowane.
W K & R C kod ten opierałby się na konkretnej klasie systemu, na której rozwijał się K&r, naiwnie przesuwając 1
bity z lewej strony podczas wykonywania lewego przesunięcia podpisanej Liczby (i ten kod również opiera się na reprezentacji dopełniacza 2), ale niektóre inne systemy nie dzielą tych właściwości, więc proces standaryzacji C nie zdefiniował tego zachowania.
Więc ten przykład jest naprawdę ciekawostką historyczną jest to, że od 1989 roku (jeśli nie wcześniej) nie powinno się go używać w żadnym prawdziwym kodzie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-11 13:26:39
Używając przykładu: int x = 0xF994, p = 4, n = 3; int z = getbits (x, p, n);
I skupiając się na tym zestawie operacji ~(~0
Dla dowolnego zestawu bitów (10010011 itd.) chcesz wygenerować "maskę", która pobiera tylko te bity, które chcesz zobaczyć. Więc 10010011 lub 0x03, jestem zainteresowany xxxxx011. Jaka Maska wyciągnie ten zestaw ? 00000111 teraz chcę mieć Rozmiar Int niezależny, pozwolę maszynie wykonać pracę tzn. zacząć od 0 dla maszyny bajtowej jest to 0x00 dla word machine to 0x0000 itp. 64-bitowa maszyna reprezentowałaby 64 bity lub 0x00000000000000000
Teraz zastosuj "Nie "(~0) i uzyskaj 11111111
przesuń w prawo (
i " nie " to i dostać 00000111
so 10010011 & 00000111 = 00000011
Pamiętasz jak działają operacje logiczne ?
W ANSI C ~0 >> n
powoduje nieokreślone zachowanie
/ / post o przesunięciu w lewo powodującym problem jest błędny.
Unsigned char m, l;
M = ~0 > > 4; wytwarza 255 i jest równa ~0, ale
M = ~0; l = m > > 4; daje poprawną wartość 15 taką samą jak:
M = 255 > > 4;
Nie ma problemu z przesunięciem w lewo ujemnym ~0 <<
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-23 00:53:47