Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use the Bitwise-Shift operator for values in a C enum definition?

Apple sometimes uses the Bitwise-Shift operator in their enum definitions. For example, in the CGDirectDisplay.h file which is part of Core Graphics:

enum {
  kCGDisplayBeginConfigurationFlag  = (1 << 0),
  kCGDisplayMovedFlag           = (1 << 1),
  kCGDisplaySetMainFlag         = (1 << 2),
  kCGDisplaySetModeFlag         = (1 << 3),
  kCGDisplayAddFlag         = (1 << 4),
  kCGDisplayRemoveFlag          = (1 << 5),
  kCGDisplayEnabledFlag         = (1 << 8),
  kCGDisplayDisabledFlag        = (1 << 9),
  kCGDisplayMirrorFlag          = (1 << 10),
  kCGDisplayUnMirrorFlag        = (1 << 11),
  kCGDisplayDesktopShapeChangedFlag = (1 << 12)
};
typedef uint32_t CGDisplayChangeSummaryFlags;

Why not simply use incrementing int's like in a "normal" enum?

like image 358
Dave Avatar asked Oct 22 '10 18:10

Dave


People also ask

What is the use of bitwise shift operator?

The bitwise shift operators move the bit values of a binary object. The left operand specifies the value to be shifted. The right operand specifies the number of positions that the bits in the value are to be shifted. The result is not an lvalue.

Why is Bitwise operator useful?

Because they allow greater precision and require fewer resources, bitwise operators can make some code faster and more efficient. Examples of uses of bitwise operations include encryption, compression, graphics, communications over ports/sockets, embedded systems programming and finite state machines.

What does it mean to bit shift a value?

Bit shifting is an operation done on all the bits of a binary value in which they are moved by a determined number of places to either the left or right. Bit shifting is used when the operand is being used as a series of bits rather than as a whole.

What is Bitwise operator in C#?

C# provides 4 bitwise and 2 bit shift operators. Bitwise and bit shift operators are used to perform bit level operations on integer (int, long, etc) and boolean data. These operators are not commonly used in real life situations.


4 Answers

Maybe writing the values in hexadecimal (or binary) helps :-)

enum {   kCGDisplayBeginConfigurationFlag  = (1 << 0), /* 0b0000000000000001 */   kCGDisplayMovedFlag               = (1 << 1), /* 0b0000000000000010 */   kCGDisplaySetMainFlag             = (1 << 2), /* 0b0000000000000100 */   kCGDisplaySetModeFlag             = (1 << 3), /* 0b0000000000001000 */   kCGDisplayAddFlag                 = (1 << 4), /* 0b0000000000010000 */   kCGDisplayRemoveFlag              = (1 << 5), /* 0b0000000000100000 */   kCGDisplayEnabledFlag             = (1 << 8), /* 0b0000000100000000 */   kCGDisplayDisabledFlag            = (1 << 9), /* 0b0000001000000000 */   kCGDisplayMirrorFlag              = (1 << 10),/* 0b0000010000000000 */   kCGDisplayUnMirrorFlag            = (1 << 11),/* 0b0000100000000000 */   kCGDisplayDesktopShapeChangedFlag = (1 << 12) /* 0b0001000000000000 */ }; 

Now you can add them (or "or" them) and get different values

kCGDisplayAddFlag | kCGDisplayDisabledFlag /* 0b0000001000010000 */ 
like image 85
pmg Avatar answered Oct 05 '22 04:10

pmg


This way you can add multiple flags together to create a "set" of flags and can then use & to find out whether any given flag is in such a set.

You couldn't do that if it simply used incrementing numbers.

Example:

int flags = kCGDisplayMovedFlag | kCGDisplaySetMainFlag; // 6 if(flags & kCGDisplayMovedFlag) {} // true if(flags & kCGDisplaySetModeFlag) {} // not true 
like image 32
sepp2k Avatar answered Oct 05 '22 04:10

sepp2k


New in C# 7 is finally adding binary literals, so you can just write it as this:

enum MyEnum
{
    kCGDisplayBeginConfigurationFlag  = 0b0000000000000001;
    kCGDisplayMovedFlag               = 0b0000000000000010;
    kCGDisplaySetMainFlag             = 0b0000000000000100;
    kCGDisplaySetModeFlag             = 0b0000000000001000;
    kCGDisplayAddFlag                 = 0b0000000000010000;
    kCGDisplayRemoveFlag              = 0b0000000000100000;
    kCGDisplayEnabledFlag             = 0b0000000001000000;
    kCGDisplayDisabledFlag            = 0b0000000010000000;
    kCGDisplayMirrorFlag              = 0b0000000100000000;
    kCGDisplayUnMirrorFlag            = 0b0000001000000000;
    kCGDisplayDesktopShapeChangedFlag = 0b0000010000000000;
};

And if you want to make things even neater, you use this: _ which is also new to C# 7, which allows you to put spaces in numbers to make things more readable, like so:

enum MyEnum
{
    kCGDisplayBeginConfigurationFlag  = 0b_0000_0000_0000_0001;
    kCGDisplayMovedFlag               = 0b_0000_0000_0000_0010;
    kCGDisplaySetMainFlag             = 0b_0000_0000_0000_0100;
    kCGDisplaySetModeFlag             = 0b_0000_0000_0000_1000;
    kCGDisplayAddFlag                 = 0b_0000_0000_0001_0000;
    kCGDisplayRemoveFlag              = 0b_0000_0000_0010_0000;
    kCGDisplayEnabledFlag             = 0b_0000_0000_0100_0000;
    kCGDisplayDisabledFlag            = 0b_0000_0000_1000_0000;
    kCGDisplayMirrorFlag              = 0b_0000_0001_0000_0000;
    kCGDisplayUnMirrorFlag            = 0b_0000_0010_0000_0000;
    kCGDisplayDesktopShapeChangedFlag = 0b_0000_0100_0000_0000;
};

Makes it so much easier to keep track of the numbers.

like image 39
AustinWBryan Avatar answered Oct 05 '22 05:10

AustinWBryan


If you have FlagA=1, FlagB=2 and FlagC=3, FlagA or FlagB would give the same value as FlagC. The shift operator is used to ensure that every combination of flags is unique.

like image 22
Florian Avatar answered Oct 05 '22 04:10

Florian