Co oznacza „(int) wartość i 0x1, (int) wartość i 0x2, (int) wartość i 0x4, (int) wartość i 0x8”?

11

kod

„Wartość” wynosi od 0 do 15 (możliwe wartości). Kiedy te 4 warunki „jeśli” zostaną spełnione? Jeśli moja (int) wartość = 2, czy to oznacza 0010?

            if  ((int)value & 0x1) 
            {
                //statement here
            }
            if  ((int)value & 0x2) 
            {
                //statement here
            }
            if  ((int)value & 0x4) 
            {
                //statement here
            }
            if  ((int)value & 0x8) 
            {
                //statement here
            }
Sean McCarthy
źródło
3
Są to maski bitowe sprawdzające poszczególne bity value(czytane if(value & 0x4)jako „Czy trzeci bit valuezestawu (= 1)). Ponieważ pozornie masz problemy ze zrozumieniem kodu, zakładam, że nie jest on twój. To (i fakt, że nie pytasz do wglądu) sprawia, że to pytanie off-topic dla CR.SE .
Nikt
Dla lepszego zrozumienia podobny kod, który został przeniesiony do C #, użyje Enum.HasFlagmetody do testowania bitów. Zobacz: Enum.HasFlag .
rwong

Odpowiedzi:

12

Każda liczba może być wyrażona jak value = b0*2^0 + b1*2^1 + b2*2^2 + b3*2^3 + ...przy każdym b będącym jednym 0lub 1(są to bity reprezentacji). To jest reprezentacja binarna.

Binarny AND ( &) sprawia, że ​​każda z tych bpar jest mądra i wykonuje AND. Ma to następujące wyniki:

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

Używając potęg 2 (które mają tylko jeden bit), możemy wyizolować i przetestować poszczególne bity:

  • value & 1jest prawdziwe, gdy valuejest nieparzysty {1, 3, 5, 7, 9, 11, 13, 15}.

  • value & 2jest prawdziwe, gdy value/2jest nieparzysty {2, 3, 6, 7, 10, 11, 14, 15}.

  • value & 4jest prawdziwe, gdy value/4jest nieparzysty {4, 5, 6, 7, 12, 13, 14, 15}.

  • value & 8jest prawdziwe, gdy value/8jest nieparzyste {8, 9, 10, 11, 12, 13, 14, 15}.

Prefiks 0x na liczbach oznacza, że ​​należy go interpretować jako liczbę szesnastkową . Jest to trochę zbędne, gdy wchodzisz tylko do 0x8, ale mówi opiekunom, że prawdopodobnie jest używany jako maska ​​bitowa.

maniak zapadkowy
źródło
1
Sformułowanie może sugerować, że można go rozszerzyć na wszystkie liczby, co nie jest prawdą: 8/6jest nieparzyste, a 8&6daje fałsz.
Sjoerd
@ Sjoerd dlatego powiedziałem „potęgi 2”
maniak zapadkowy
5

Te instrukcje if sprawdzają, czy określony bit valuejest ustawiony.

Na 0x4przykład wartość szesnastkowa ma trzeci bit od prawego zestawu do 1i wszystkie inne bity ustawione na 0. Gdy użyjesz operatora binarnego i operatora ( &) z dwoma operantami, w wyniku zostaną ustawione wszystkie bity z 0wyjątkiem bitów, które mają 1 w obu operantach.

Więc kiedy wykonujesz obliczenia value & 0x4, dostajesz binarny 00000000lub binarny 00000100, w zależności od tego, czy trzeci bit valuejest, 1czy nie 0. Pierwszy ocenia na false, a drugi na true, więc blok if jest wykonywany tylko dla wartości, dla których ustawiony jest trzeci bit.

Philipp
źródło
1

Warto tu zwrócić uwagę na dwie interesujące rzeczy.

Po pierwsze, jest to powszechny wzorzec sprawdzania każdego z 4 bitów niższego rzędu o wartości całkowitej. Warunek if jest spełniony, jeśli ustawiony jest odpowiedni bit. Dla wartości 2 wzorzec bitowy jest rzeczywiście 0010.

Innym bardziej interesującym pytaniem jest dlaczego (int)obsada? Poza złym stylem używania rzutowań C w C ++, żadne wartości całkowite ani znaki nie wymagają tego rzutowania. Bool nie ma sensu, podwójny / zmiennoprzecinkowy zostałby przekonwertowany na liczbę całkowitą tymczasową i byłoby rzadkością używać literałów do testowania wyliczenia. Może to mieć sens ze wskaźnikiem, ale byłoby to bardzo wyspecjalizowane zastosowanie. Wniosek: obsada nie ma sensu.

david.pfx
źródło