44

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?

Dave
  • 12,408
  • 12
  • 64
  • 67
  • 1
    Related question: http://stackoverflow.com/questions/2159138/c-bitwise-operator-in-enum-custom-authorization-in-mvc – Oded Oct 22 '10 at 18:48
  • 1
    It makes it easy to see that the enum are all flags with only a single bit set. – Martin York Oct 22 '10 at 19:26
  • 7
    Actually the real reason as Loki pointed out is for readability. You could use 1, 2, 4, 8, 16 and so on (powers of 2) but you run the risk of making mistakes whereas 1 << 0, 1 << 1, 1 << 2, 1 << 3 is easier to key in and read while leaving it to the compiler to do the actual value computation. If you want to program smart then you need to know what the compiler can do for you and leverage its capabilities. – Telemat Jun 29 '14 at 04:06

9 Answers9

101

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 */
pmg
  • 106,608
  • 13
  • 126
  • 198
  • 8
    SO clear, you might consider setting this as the accepted answer. – deed02392 Sep 27 '13 at 00:31
  • What would be the limitations with this? Would there be a maximum of, say, 16 values you can put into this enum before you run out of possibilities? – mylogon Feb 15 '17 at 13:10
  • 1
    @mylogon: It's implementation dependent. C11 guarantees`unsigned int` can hold 16 bits, `unsigned long` can hold 32 bits as a minimum. – pmg Feb 15 '17 at 17:44
64

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
sepp2k
  • 363,768
  • 54
  • 674
  • 675
5

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.

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
  • 1
    I was looking to ensure what I wanted to do was legit in C. This thread is specifically about enums and bitwise operators in C. There seem to be a lot of other threads out there about enums and bitwise ops specifically for C#. I'm not sure adding details about C# to *this* thread is helpful. – CarlRJ Oct 28 '19 at 20:21
4

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.

Florian
  • 3,145
  • 1
  • 27
  • 38
2

This will allow for a variable to easily combine multiple flags:

unit32_t multFlag = kCGDisplayRemoveFlag | kCGDisplayMirrorFlag | kCGDisplaySetMainFlag'
Vladimir
  • 170,431
  • 36
  • 387
  • 313
1

I got an enum with flags as follows.

[Flags]
public enum PlatformOptions
{
    None = 0,
    Connectivity = 1,
    LiveVideo = 1 << 2,
    OnDeviceWithProbe = 1 << 3,
    ForceAnalyzeFeatureSet = 1 << 4,
    EnableGstreamerLiveADR = 1 << 5,
}

Now I have got its value like this.

var None = 0;
var Connectivity = 1;
var LiveVideo = 1 << 2;
var OnDeviceWithProbe = 1 << 3;
var ForceAnalyzeFeatureSet = 1 << 4;
var EnableGstreamerLiveADR = 1 << 5;

System.Console.WriteLine(None); // Returns 0
System.Console.WriteLine(Connectivity); // Returns 1
System.Console.WriteLine(LiveVideo); // Returns 4
System.Console.WriteLine(OnDeviceWithProbe); // Returns 8
System.Console.WriteLine(ForceAnalyzeFeatureSet); // Returns 16
System.Console.WriteLine(EnableGstreamerLiveADR); // Returns 32
VivekDev
  • 20,868
  • 27
  • 132
  • 202
0

.. because 1<<7 looks more concise and easier to read than 01000000. Doesn't it?

N 1.1
  • 12,418
  • 6
  • 43
  • 61
0

Let's me give you a more practice example. In c++ when you want to open a file (Open for output, and in binary mode opposed to text mode), you can do it by:

const char *filename = "/home/xy/test.bin";
fstream output(filename, ios::out | ios::binary);

You can see, ios::out | ios::binary can set two mode(Open for output, and in binary mode).

How does this work ? It's by enum(bitwise-shift values):

enum _Ios_Openmode 
{ 
  _S_app        = 1L << 0,
  _S_ate        = 1L << 1,
  _S_bin        = 1L << 2,  /* 0b0000000000000100 */
  _S_in         = 1L << 3,
  _S_out        = 1L << 4,  /* 0b0000000000010000 */
  _S_trunc      = 1L << 5
  //.....
};

/// Perform input and output in binary mode (as opposed to text mode).
static const openmode binary =  _S_bin;

/// Open for input.  Default for @c ifstream and fstream.
static const openmode in =      _S_in;

/// Open for output.  Default for @c ofstream and fstream.
static const openmode out =     _S_out;

If you use value increment by 1 in enum _Ios_Openmode, you have to set(ios::out) and set(ios::binary) do two times. It may not so convenient to check and set value by one time.

Jayhello
  • 5,931
  • 3
  • 49
  • 56
-6

using #define is more understandable. but enum could group these value togater.

richard
  • 1,607
  • 6
  • 15
  • 18