Reputation: 171
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
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
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
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
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
Reputation: 6095
The numeric values that DISP_x are equal:
DISP_1 == 0x10000
DISP_2 == 0x10001
DISP_3 == 0x10002
...
Upvotes: 0