位字段与Bitset

时间:2010-10-22 14:59:27

标签: c++ bit-fields bitset

我想在数组中存储位(如结构)。所以我可以遵循以下两种方法之一

方法1(AN 1)

struct BIT
{
   int data : 1
};

int main()
{
   BIT a[100];
   return 0;
}

方法2(AN 2)

int main()
{
    std::bitset<100> BITS;
    return 0;
}

为什么有人比AN 1更喜欢AN 2?

5 个答案:

答案 0 :(得分:19)

因为接近nr。 2实际上使用100位存储,加上一些非常小的(恒定的)开销,而nr。 1通常每Bit个结构使用四个字节的存储空间。通常,struct每个C ++标准至少有一个字节大小。

#include <bitset>
#include <iostream>

struct Bit { int data : 1; };

int main()
{
    Bit a[100];
    std::bitset<100> b;
    std::cout << sizeof(a) << "\n";
    std::cout << sizeof(b) << "\n";
}

打印

400
16

除此之外,bitset将您的位数组包装在一个具有许多有用操作的漂亮对象表示中。

答案 1 :(得分:6)

一个好的选择取决于你将如何使用这些位。

std::bitset<N>具有固定大小。 Visual C ++ 10.0是不符合的wrt。建设者;一般来说,你必须提供一种解决方法。具有讽刺意味的是,这是因为微软认为这是一个错误修复 - 我记得他们引入了一个带int参数的构造函数。

std::vector<bool>的优化方式与std::bitset的优化方式大致相同。成本:索引不直接提供引用(C ++中没有对单个位的引用),而是返回一个代理对象 - 在您尝试将其用作引用之前,这不是您注意到的。优点:存储空间最小,可以根据需要调整矢量大小。

只需使用例如unsigned也是一个选项,如果你要处理少量的比特(实际上,32或更少,虽然正式保证只有16位)。

最后,所有UPPERCASE标识符按照惯例(Microsoft除外)为宏保留,以减少名称冲突的可能性。因此,不要将所有大写标识符用于除宏以外的任何其他内容,这是一个好主意。并且始终对宏使用ALL UPPERCASE标识符(这也使得识别它们更容易)。

干杯&amp;第h。,

答案 2 :(得分:2)

bitset有more operations

答案 3 :(得分:0)

方法编号1很可能被编译为4字节整数数组,每个数组中的一位将用于存储数据。从理论上讲,智能编译器可以对此进行优化,但我不会指望它。

您是否有理由不想使用std::bitset

答案 4 :(得分:0)

引用cplusplus.com's page on bitset,“该类与常规数组非常相似,但优化了空间分配”。如果你的int是4个字节,则bitset使用的空间减少32倍。

正如sbi建议的那样,即使做bool bits[100],仍然比bitset更糟糕,因为大多数实现都有> = 1字节的bools。

如果出于好奇心的原因,你想要实现自己的bitset,你可以使用位掩码:

typedef struct {
  unsigned char bytes[100];
} MyBitset;

bool getBit(MyBitset *bitset, int index)
{
  int whichByte = index / 8; 
  return bitset->bytes[whichByte] && (1 << (index = % 8));
}

bool setBit(MyBitset *bitset, int index, bool newVal)
{
  int whichByte = index / 8;

  if (newVal)
  {
    bitset->bytes[whichByte] |= (1 << (index = % 8));
  }
  else
  {
    bitset->bytes[whichByte] &= ~(1 << (index = % 8));
  }
}

(很抱歉顺便使用结构而不是类。我正在考虑直接C,因为我正处于学校的低级任务中。显然,使用类的两个巨大好处是运算符重载和具有可变大小数组的能力。)