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!)

Jakaś pomoc?
Author: Gaurang Tandon, 2008-10-13

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 !!

 34
Author: paxdiablo,
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.

  1. Nasza liczba to 75 chcemy 4 bity zaczynając od pozycji 6. wywołaniem funkcji będzie getbits(75,6,4);

  2. 75 W binarnym jest 0100 1011

  3. Tworzymy więc maskę o długości 4 bitów, zaczynając od bitu najniższego rzędu.

~0 = 1111 1111
~ = 0000 1111

Dobra, mamy maskę.
  1. 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.

  1. 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.

 11
Author: None,
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.

 6
Author: David Grant,
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 jest E1 przesunięte w lewo E2 pozycje bitowe; puste bity są wypełnione zerami. [...] Jeżeli E1 ma podpis typ i wartość nonnegatywna oraz E1 × 2E2 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.

 3
Author: M.M,
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 ?

 2
Author: ,
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 14:00:48

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 <<

 -2
Author: Surfer Boy,
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