什么是标志和位域?

时间:2013-03-10 00:55:58

标签: c++ flags bit-fields

有人可以向我解释一下标志和位域是什么。他们似乎彼此相关,或者说我错了想法。我有点掌握他们所做的事情,但是我想让他们完全解释,我找不到任何好的教程或指南。

如果有人可以提供一些关于如何使用它们的好例子,我会非常感激...例如,我一直看到这些表达式并且我不完全理解它们。只是他们是某种逻辑运算符或其他东西

  VARIABLE1 | VARIABLE2

提前致谢!

4 个答案:

答案 0 :(得分:3)

可以在此处找到按位操作的介绍:http://www.codeproject.com/Articles/2247/An-introduction-to-bitwise-operators

当它们应用于标志时,按位操作是有利的,因为它们非常快并且节省空间。您可以使用互斥位将对象的许多不同状态存储在单个变量中。即

0001 // property 1 (== 1, 0x01)
0010 // property 2 (== 2, 0x02)
0100 // property 3 (== 4, 0x04)
1000 // property 4 (== 8, 0x08)

这些可以表示对象的四种不同属性(这些是“掩码”)。我们可以使用or

将属性添加到对象的flags状态
short objState = 0; // initialize to 0
objState |= 0010;

这将上面的属性2添加到objState by“或”-ing 0010 with 0000,结果为0010.如果我们添加另一个标志/属性,如下所示:

objState |= 0100;

我们最终得到了objState = 0110。

现在我们可以检查对象是否具有属性2集的标志,例如,使用and

if (objState & 0010) // do something
当且仅当两个位都为1时,

and为1,因此如果位2为1,则上述操作保证为非零。

正如我所提到的,这种处理对象属性/标志的方法的优点是速度和效率。可以这样想:您可以使用此方法将一组属性存储在单个变量中。

例如,假设您有一个文件类型,并希望使用位掩码跟踪属性(我将使用音频文件)。也许位0-3可以存储文件的位深度,位4-7可以存储文件类型(Wav,Aif等),等等。然后,您只需要将这一个变量传递给不同的函数,并且可以使用您定义的位掩码进行测试,而不必跟踪可能的数十个变量。

希望至少对这种按位操作的应用有所了解。

答案 1 :(得分:0)

整数值的位可以用作bools。

http://msdn.microsoft.com/en-us/library/yszfawxh(v=vs.80).aspx

使用|制作并使用&进行检索。

enum { ENHANCED_AUDIO = 1, BIG_SPEAKERS = 2, LONG_ANTENNA = 4};

foo(HAS_CAR | HAS_SHOE); // equiv to foo(3);

void processExtraFeatures(flags) {
    BOOLEAN enhancedAudio = flags & ENHANCED_AUDIO; // true
    BOOLEAN bigSpeakers = flags & BIG_SPEAKERS; // true
    BOOLEAN longAntenna = flags & LONG_ANTENNA; // false
}

答案 2 :(得分:0)

“flag”是可以设置或不设置的名义对象,但不是c ++语言的一部分。

位域是一种语言结构,用于使用可能不构成可寻址对象的位组。单个字段是一个 - 通常非常好 - 实现标志的方式。

答案 3 :(得分:0)

“bifield”是“word”中的一个或多个位(即,intlongchar),它们一起存储在一个变量中。

例如,你可以在一些动物上有“无”,“斑点”和/或“条纹”,它也可以有“无,短,中或长”的尾巴。

因此,我们需要两位代表尾部的长度:

enum tail
{
   tail_none = 0,
   tail_short = 1, 
   tail_medium = 2, 
   tail_long = 3
};

然后我们将这些作为位存储在“属性”中:

enum bits_shifts
{
   tail_shift = 0,    // Uses bits 0..1
   spots_shift = 2,   // Uses bit 2
   stripes_shift = 3
};


enum bits_counts
{
   tail_bits = 2,    // Uses bits 0..1
   spots_bits = 1,   // Uses bit 2
   stripes_bits = 1
};

我们现在假装我们从一些输入中获取了tail_size和has_stripes,has_spots变量。

int attributes;

attributes = tail_length << tail_shift;

if (has_spots)
{
   attributes |= 1 << spots_shift;
}

if (has_stripes)
{
   attributes |= 1 << stripes_shift;
}

稍后我们想要确定属性是什么:

switch((attributes >> tail_shift) & (1 << tail_bits)-1))
{
   case tail_none:
     cout << "no tail";
     break;

   case tail_short:
     cout << "short tail";
     break;

   case tail_medium:
     cout << "medium tail";
     break;

   case tail_short:
     cout << "long tail";
     break;
 }

 if (attributes & (1 << stripes_shift))
 {
    cout << "has stripes";
 }


 if (attributes & (1 << spots_shift))
 {
    cout << "has spots";
 }

现在,我们将所有这些存储在一个整数中,然后再次“捞出”。

你当然可以这样做:

enum bitfields
{
    has_widget1 = 1,
    has_widget2 = 2,
    has_widget3 = 4, 
    has_widget4 = 8, 
    has_widget5 = 16,
    ...
    has_widget25 = 16777216, 
    ...
}

int widgets = has_widget1 | has_widget5;

... 

if (widgets & has_widget1)
{
  ... 
}

这实际上只是将一些东西打包成一个变量的简单方法。