Зачем использовать оператор Bitwise-Shift для значений в определении enum C?

Apple иногда использует оператор Bitwise-Shift в своих определениях перечислений . Например, в файле CGDirectDisplay.h, который является частью 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; 

Почему бы просто не использовать инкрементные int , как в «нормальном» перечислении ?

Таким образом вы можете добавить несколько флагов вместе, чтобы создать «набор» флагов, а затем использовать & чтобы узнать, присутствует ли какой-либо данный флаг в таком наборе.

Вы не могли этого сделать, если бы просто использовали увеличивающиеся числа.

Пример:

 int flags = kCGDisplayMovedFlag | kCGDisplaySetMainFlag; // 6 if(flags & kCGDisplayMovedFlag) {} // true if(flags & kCGDisplaySetModeFlag) {} // not true 

Возможно, запись значений в шестнадцатеричном (или двоичном) помогает 🙂

 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 */ }; 

Теперь вы можете добавить их (или «или» их) и получить разные значения

 kCGDisplayAddFlag | kCGDisplayDisabledFlag /* 0b0000001000010000 */ 

Если у вас есть FlagA = 1, FlagB = 2 и FlagC = 3, FlagA или FlagB будут давать то же значение, что и FlagC. Оператор сдвига используется для обеспечения единства каждой комбинации флагов.

Это позволит переменной легко объединить несколько флагов:

 unit32_t multFlag = kCGDisplayRemoveFlag | kCGDisplayMirrorFlag | kCGDisplaySetMainFlag' 

Новое в C # 7 – это, наконец, бинарные литералы, поэтому вы можете просто написать это как это:

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

И если вы хотите сделать вещи еще более аккуратными, вы используете это: _ которое также является новым для C # 7, которое позволяет помещать пробелы в числа, чтобы сделать вещи более читаемыми, например:

 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; }; 

Делает это намного легче отслеживать цифры.

.. потому что 1<<7 выглядит более кратким и легче читать, чем 01000000 . Не так ли?

использование #define более понятно. но перечисление может группировать эти значения togater.

Давайте будем гением компьютера.