Wint
Wint

Reputation: 171

Reproducing some bit shift code from C++ to C#

I'm trying to convert an enum from C++ code over to C# code, and I'm having trouble wrapping my head around it. The C++ code is:

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
}

What I don't understand is what MASK is doing, and how I can either emulate the functionality in C#, or understand what it's doing and set the enum DISP manually without it.

I'm not sure what I'm saying is making sense, but that's to be expected when I'm not entirely certain what I'm looking at.

Upvotes: 6

Views: 622

Answers (5)

ohmusama
ohmusama

Reputation: 4215

when you bit shift, it shifts all the 1's and 0's to the left or right by some number of values.

in your case 1 << 16 creates 10000000000000000 in binary. (yes that is 16 zeros).

Then it takes that number and uses | which is the bitwise-or operator. thus, whatever the integer value of the enum is, it gets bitwise-ored into that number we bit shifted.

If for example, you use MASK(FOO_4) (which has the literal value of 3) 3 is 11 in binary, so the result would be 10000000000000011. This is functionally the same as adding 65,536 to each value.

Now, when we declare the second enum, we are setting the values of those enum values to this weird masking function.

To do the same thing in c# try this:

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

Upvotes: 7

Robert Rouhani
Robert Rouhani

Reputation: 14668

Just replace MASK with what it's defined as (the << and | operators exist in C# too) :

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

If you're wondering exactly what the shift and or operators do, you're taking the binary value of 0000000000000001 and shifts it 16 values to the left: 1000000000000000.

Another example, (000001101 << 3) becomes 001101000.

The or operator takes all the 1 values from either operand and sets the value of the result to 1.

For example, 0001 | 0110 becomes 0111.

So then, take DISP_2:

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

(I know the 0b format doesn't work in C# and isn't standard in C, but it's more useful to use binary notation instead of hexadecimal, easier to see what the operators are doing)

Upvotes: 2

Theraot
Theraot

Reputation: 40130

The bit shift operator works in C#, but the define macro doesn't.

To understand what's going on you can do is calculate the values separately and then put them in the enum.

Of course you know that | is the bitwise OR operator. And just in case what the operator << does is shift the binary to the left:

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

In turn:

10000000000000000_2 = 65536

That is the quivalent of mutiplying the number by 2 the number of times indicated by the second operand.

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

That's right, it is multiplying the number by a power of two:

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

Now, Since FOO_1 = 0 then

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

Doing the same for FOO_2 which I take has the value 1 will give you:

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

With that said the following works correctly:

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
}

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

MASK(x) constructs a number by OR-ing in a number x with a binary number 10000000000000000 (one shifted to the left 16 times).

In C# you can use an expression directly, like this:

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
}

Upvotes: 6

Serge
Serge

Reputation: 6095

The numeric values that DISP_x are equal:

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

Upvotes: 0

Related Questions