Зачем использовать оператор 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 , как в «нормальном» перечислении ?
- C # vs Java Enum (для тех, кто не знаком с C #)
- Получить перечисление из атрибута enum
- Можете ли вы просмотреть все значения enums?
- Как создать таблицу, соответствующую перечислению в EF6 Code First?
- Как сравнить флаги в C #?
Таким образом вы можете добавить несколько флагов вместе, чтобы создать «набор» флагов, а затем использовать &
чтобы узнать, присутствует ли какой-либо данный флаг в таком наборе.
Вы не могли этого сделать, если бы просто использовали увеличивающиеся числа.
Пример:
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.