标志如何在C中起作用?

Jus*_*ers 12 c c++ flags integer

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

FLAG1 = 0x00000001,
FLAG2 = 0x00000010,
Run Code Online (Sandbox Code Playgroud)

我的直觉表明这些价值正在被合并.通过将所有标志值组合到一个int中,标志是否有效?如果我使用了这两个,FLAG1 | FLAG2结果会是0x00000011什么?

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

FLAG1 = 1;
FLAG2 = 2;
Run Code Online (Sandbox Code Playgroud)

jtb*_*des 28

您需要偏移位,否则无法提取单个标志.如果你有对应于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
};
Run Code Online (Sandbox Code Playgroud)

然后你像这样组合标志:

int flags = FIRST | THIRD | FOURTH;
Run Code Online (Sandbox Code Playgroud)

你像这样提取它们:

if (flags & THIRD) { ...
Run Code Online (Sandbox Code Playgroud)


Mar*_*ers 8

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

TEXTUREFLAGS_POINTSAMPLE = 1,
TEXTUREFLAGS_TRILINEAR = 16,
Run Code Online (Sandbox Code Playgroud)

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

您应该使用这些值:

0x00000001  // == 1
0x00000002  // == 2
0x00000004  // == 4
0x00000008  // == 8
0x00000010  // == 16
0x00000020  // == 32
0x00000040  // == 64
etc...
Run Code Online (Sandbox Code Playgroud)

这些是2的幂,它们可以使用按位或以任何方式组合而不会发生冲突.


Pau*_*lin 5

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


Jam*_*mes 5

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

要打开这些位之一,请使用 1 << BitIndex 或它(其中 BitIndex 从零开始,因此 0 - 31) 要关闭其中一个位,请使用 ~(1 << BitIndex) 或它来检查它是打开还是关闭你将它与 (1 << BitIndex)

一旦你克服了数字 OR/AND 与逻辑 OR/AND 之间的差异,一切都会迎刃而解。然后你就会欣赏十六进制表示法!