14

最近我在 C 和 C++ 中遇到了几个“标志”的例子,我不太明白它们是如何工作的。在查看了一些源代码后,我注意到标志值通常以十六进制定义,如下所示:

FLAG1 = 0x00000001,
FLAG2 = 0x00000010,

我的直觉表明这些价值观正在被结合起来。标志是否通过将所有标志值组合成一个 int 来工作?如果我同时使用这两种方法FLAG1 | FLAG2,结果会是0x00000011什么?

我是否需要创建具有位偏移的枚举,或者我可以使用升序整数如:

FLAG1 = 1;
FLAG2 = 2;
4

4 回答 4

36

您需要偏移这些位,否则无法提取各个标志。如果您有对应于 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) { ...
于 2010-09-04T19:29:25.863 回答
10

您的第一种方法不是以最有效的方式使用这些位。在第一个示例中,您使用的是十六进制表示法,它相当于:

TEXTUREFLAGS_POINTSAMPLE = 1,
TEXTUREFLAGS_TRILINEAR = 16,

在第二种方法中,您似乎只是每次增加一个。这在您组合标志时不起作用,因为组合值可能与另一个标志相同(例如,1 | 2 == 3)。

您应该改用这些值:

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

这些是两个的幂,它们可以使用按位或以任何方式组合而不会产生冲突。

于 2010-09-04T19:28:21.830 回答
5

像这样的标志是二进制值,因此您可以将 1、2、4、8、16、32、64、128 组合在一个字节中,或者将 2 到 2^31 的进一步幂组合到一个 int 中。因为它们是二进制值,所以您可以将它们“或”在一起,例如,如果将 1、2、4 一起“或”在一起,您最终会得到 7。您可以使用“and”提取您想要的位 - 因此,如果您有一个带有一些标志的 int 或一起,并且您想查看是否设置了“4”位,您可以说if (flag & 4),如果“4”位已设置。

于 2010-09-04T19:32:05.467 回答
4

将标志视为 32 位数组(布尔值)

用 1 << BitIndex 将这些位中的一个或它(其中 BitIndex 是从零开始的,所以 0 - 31)关闭一个,用 ~(1 << BitIndex) 检查它是打开还是关闭你和它 (1 << BitIndex)

Once you get over the difference between digital OR/AND against logical OR/AND it'll all click. Then you'll appreciate hexadecimal notation!

于 2010-09-04T19:47:10.007 回答