Как работают флаги в C? - PullRequest
       4

Как работают флаги в C?

11 голосов
/ 04 сентября 2010

Недавно я натолкнулся на несколько примеров «флагов» в C и C ++, и я не совсем понимаю, как они работают. Посмотрев некоторый исходный код, я заметил, что часто значения флагов определяются в шестнадцатеричном формате, например:

FLAG1 = 0x00000001,
FLAG2 = 0x00000010,

Мой интуитивно предполагает, что эти значения объединяются. Работают ли флаги, объединяя все значения флагов в одно целое? Если бы я использовал оба из них, как FLAG1 | FLAG2, результат был бы 0x00000011?

Нужно ли создавать перечисления с битовыми смещениями или я могу использовать возрастающие целые числа, такие как:

FLAG1 = 1;
FLAG2 = 2;

Ответы [ 4 ]

29 голосов
/ 04 сентября 2010

Вам нужно сместить биты, иначе нет способа извлечь отдельные флаги.Если у вас есть флаги, соответствующие 1, 2, 3 и 4, и объединенное значение 5, как вы можете определить, было ли это 2 & 3 или 1 & 4?

Вы можете сделать это такжеНапример:

enum {
    FIRST = 1 << 0, // same as 1
    SECOND = 1 << 1, // same as 2, binary 10
    THIRD = 1 << 2, // same as 4, binary 100
    FOURTH = 1 << 3 // same as 8, binary 1000
};

Затем вы комбинируете флаги следующим образом:

int flags = FIRST | THIRD | FOURTH;

И извлекаете их так:

if (flags & THIRD) { ...
8 голосов
/ 04 сентября 2010

Ваш первый метод не использует биты самым эффективным способом. В первом примере вы используете шестнадцатеричное обозначение, и оно эквивалентно:

TEXTUREFLAGS_POINTSAMPLE = 1,
TEXTUREFLAGS_TRILINEAR = 16,

Во втором методе кажется, что вы просто увеличиваете на единицу каждый раз. Это не будет работать, когда вы комбинируете флаги, потому что объединенное значение может совпадать с другим флагом (например, 1 | 2 == 3).

Вы должны использовать эти значения вместо:

0x00000001  // == 1
0x00000002  // == 2
0x00000004  // == 4
0x00000008  // == 8
0x00000010  // == 16
0x00000020  // == 32
0x00000040  // == 64
etc...

Это полномочия двух, и их можно комбинировать, используя побитовый или любой другой способ, не создавая коллизий.

5 голосов
/ 04 сентября 2010

Флаги, подобные этому, являются двоичными значениями, поэтому вы можете комбинировать 1, 2, 4, 8, 16, 32, 64, 128 в одном байте или дополнительные степени от 2 до 2 ^ 31 в целом числе. Поскольку они являются двоичными значениями, вы можете "или" их вместе, поэтому, если вы "или" вместе 1,2,4, вы получите 7, например. И вы можете извлечь нужный бит, используя «и» - так что если у вас есть int с некоторыми флагами или вместе, и вы хотите увидеть, установлен ли бит «4», вы можете сказать if (flag & 4), и он будет быть истинным, если установлен бит "4".

3 голосов
/ 04 сентября 2010

Думайте о флагах как о 32-битном массиве (логическое значение)

Чтобы включить один из этих битов на вас ИЛИ на него 1 << BitIndex (где BitIndex начинается с нуля, поэтому 0 - 31) Чтобы отключить вас и это с помощью ~ (1 << BitIndex) Чтобы проверить, включен он или нет, вы И это с помощью (1 << BitIndex) </p>

Как только вы преодолеете разницу между цифровым ИЛИ / И и логическим ИЛИ / И, все щелкнет. Тогда вы оцените шестнадцатеричное представление!

...