2012-10-12 2 views
5

Próbuję przekonwertować wyliczenie z kodu C++ na kod C# i mam problem z owinięciem się wokół niego. C kod ++ to:Odtwarzanie kodu przesunięcia bitowego z C++ do C#

enum FOO { 
    FOO_1 = 0, 
    FOO_2, 
    // etc 
} 

#define MASK(x) ((1 << 16) | (x)) 

enum DISP 
{ 
    DISP_1 = MASK(FOO_1), 
    DISP_2 = MASK(FOO_2), 
    // etc 
} 

Co ja nie rozumiem, co MASK robi, i jak mogę albo naśladować funkcjonalność w C#, lub zrozumieć, co robi i ustawić DISP enum ręcznie bez niego.

Nie jestem pewien, co mówię, ma sens, ale tego można się spodziewać, gdy nie jestem całkowicie pewien, na co patrzę.

+0

Należy przeczytać o przesunięcie (<<) i albo (|) operatorów w C++, dzięki czemu można zrozumieć, co się dzieje. – coredump

+0

Zdecydowanie będę! – Wint

Odpowiedz

5

MASK(x) konstruuje liczbę przez OR -ing w wielu x z liczby binarnej 10000000000000000 (jeden przesunął się w lewo 16 razy).

W języku C# można użyć bezpośrednio wyraz, podobnie jak to:

enum FOO { 
    FOO_1 = 0, 
    FOO_2, 
    // etc 
} 

enum DISP 
{ 
    DISP_1 = (1<<16) | (int)(FOO.FOO_1), 
    DISP_2 = (1<<16) | (int)(FOO.FOO_2), 
    // etc 
} 
+0

To jest dokładnie to, czego szukałem. Dziękuję za przykład! – Wint

2

Wystarczy zastąpić MASK z tym, co jest zdefiniowana jako (operatorzy << i | istnieje w C# zbyt):

enum DISP 
{ 
    DISP_1 = ((1 << 16) | FOO.FOO_1), 
    DISP_2 = ((1 << 16) | FOO.FOO_2) 
} 

Jeśli zastanawiasz się, co dokładnie przesunięcie i czy operatorzy zrobić, ty” ponownie przyjmując wartość binarną 0000000000000001 i przesuwa ją o 16 wartości w lewo: 1000000000000000.

Inny przykład, (000001101 << 3), staje się 001101000.

operatora OR bierze się wszystkie wartości 1 z obu argumentów i ustawia wartość wyniku dla 1.

Na przykład 0001 | 0110 się 0111.

Więc, weź DISP_2:

(0b00000000000000001 << 16) | 0b00000000000000010) 
= (0b10000000000000000 | 0b00000000000000010) 
= (0b10000000000000010) 
= 65538 

(wiem, format, 0b nie działa w C# i nie jest standardem w C, ale jest to bardziej przydatne do korzystania binarny zapis zamiast szesnastkowym, łatwiej aby zobaczyć, co robią operatorzy)

7

kiedy bit przesunięcie, to przesuwa wszystkie 1 i 0 w lewo lub w prawo, przez pewną liczbę wartości.

w twoim przypadku 1 << 16 tworzy 10000000000000000 w postaci binarnej. (tak, to jest 16 zer).

Następnie zajmuje tę liczbę i używa |, który jest operatorem bitowym lub. w związku z tym, niezależnie od wartości całkowitej wyliczenia, jest ona podzielona bitowo na tę liczbę, którą nieco zmieniliśmy.

Jeśli na przykład używasz MASK(FOO_4) (który ma literalną wartość 3) 3 to 11 w binarnym, więc wynik będzie 10000000000000011. Jest to funkcjonalnie taki sam efekt, jak dodanie 655,536 do każdej wartości.

Teraz, gdy deklarujemy drugie wyliczenie, ustawiamy wartości tych wartości wyliczeniowych na tę dziwną funkcję maskowania.

Aby zrobić to samo w C# spróbuj tego:

enum Foo { //this may not be needed anymore? 
    FOO_1 = 0, FOO_2, ... etc 
} 

enum Disp { //DISP_2 gets the next value ie 65536 + 1, and so forth 
    DISP_1 = 65536, DISP_2, DISP_3, ... etc 
+1

Nie potrzebujesz + 1, + 2 itd., Reszta zostanie przypisana sekwencyjnie od tej określonej na początku. DISP_1 jest jedynym, który wymaga jawnej wartości przypisanej (a FOO_1 nawet nie musi być określona, ​​ponieważ zaczyna się od 0). – jrajav

+0

Dobra rozmowa, masz rację. Zapomniałem o tym. Podobnie jak PHP – ohmusama

+0

"Podobnie jak C/C++" jest prawdopodobnie bardziej trafny;) – jrajav

0

wartościami liczbowymi, które DISP_x są równe:

DISP_1 == 0x10000 
DISP_2 == 0x10001 
DISP_3 == 0x10002 
... 
0

Operator bitowy shift działa w C#, ale zdefiniować makro robi” t.

Aby zrozumieć, co się dzieje, możesz obliczyć wartości osobno, a następnie umieścić je w wyliczeniu.

Oczywiście wiesz, że | jest operatorem bitowym OR. I tak na wszelki wypadek, co operator << robi jest przesunięcie binarny do lewej:

1 << 16 = 10000000000000000_2 //those are 16 zeroes and _2 indicates binary 

kolejno:

10000000000000000_2 = 65536 

To quivalent z mutiplying liczby o 2 liczbę razy wskazanych przez drugi operand.

1 << 1 = 2 
1 << 2 = 4 
1 << 3 = 8 

To prawda, że ​​jest pomnożenie liczby przez potęgi dwójki:

1 << 1 <=> 1 * 2^1 = 2 
1 << 2 <=> 1 * 2^2 = 4 
1 << 3 <=> 1 * 2^3 = 8 

Teraz, ponieważ FOO_1 = 0 następnie

DISP_1 = MASK(FOO_1) 
=> 
DISP_1 = ((1 << 16) | (FOO_1)) 
=> 
DISP_1 = (65536 | (FOO_1)) 
=> 
DISP_1 = (65536 | FOO_1) 
=> 
DISP_1 = (65536 | 0) 
=> 
DISP_1 = 65536 

robi to samo dla FOO_2 które biorę ma wartość 1 daje:

DISP_2 = (65536 | FOO_2) 
=> 
DISP_2 = (65536 | 1) 
=> 
DISP_2 = 65537 

Z powiedział następujące prace poprawnie:

enum FOO 
{ 
    FOO_1 = 0, 
    FOO_2, 
    // etc 
} 

enum DISP 
{ 
    DISP_1 = (1<<16) | (int)(FOO.FOO_1), 
    DISP_2 = (1<<16) | (int)(FOO.FOO_2), 
    // etc 
}