我怎样才能在内存中准确输入2位?

时间:2011-11-26 15:27:42

标签: c++ bit-manipulation bit bitset memory-efficient

我应该能够在一个可以从0到3的数据结构中存储一个值。所以我需要2位。这个数据结构我将是2 ^ 16个很棒的位置。所以,我想要2 ^ 16 * 2(位)。在C ++中你是否使用内存中的2位?

7 个答案:

答案 0 :(得分:9)

每单位需要两位(而不是三位),因此可以将四个单位打包成一个字节,或将16个单位打包成一个32位整数。

所以你需要一个std::array<uint32_t, 4096>来容纳2个 16 单位的2位值。

您可以按如下方式访问 n th 值:

unsigned int get(std::size_t n, std::array<uint32_t, 4096> const & arr)
{
    const uint32_t u = arr[n / 16];
    return (u >> (2 * (n % 16))) & 0x3;
}

或者,您可以使用位域:

struct BF32 {
  uint32_t u0 : 2;
  uint32_t u1 : 2;
  //...
  uint32_t uF : 2;
}

然后制作std::array<BF32, 4096>

答案 1 :(得分:2)

您不能分配小于1个字节的单个对象(因为1个字节是系统中最小的可寻址单元)。

但是,您可以使用位域使结构的某些部分小于一个字节。您可以创建其中一个来保存8个值,其大小正好是3个字节:

#pragma pack(1) // MSVC requires this
struct three_by_eight {
  unsigned value1 : 3;
  unsigned value2 : 3;
  unsigned value3 : 3;
  unsigned value4 : 3;
  unsigned value5 : 3;
  unsigned value6 : 3;
  unsigned value7 : 3;
  unsigned value8 : 3;
}
__attribute__ ((packed)) // GCC requires this
;

使用[]无法访问这些内容可能会很笨拙....最好的方法是创建自己的类,类似于bitset但是可以工作3位而不是1。

答案 2 :(得分:1)

如果您没有使用嵌入式系统并且资源充足,您可以查看std::bitset<>,这将使您作为程序员的工作更轻松。

但是如果您正在使用嵌入式系统,那么bitset可能对您不利(您的编译器可能甚至不支持模板)。有许多操作位的技术,每种都有自己的怪癖;这是一篇可能对你有帮助的文章:
&GT; http://www.atmel.com/dyn/resources/prod_documents/avr_3_04.pdf

答案 3 :(得分:0)

0到3有4个可能的值。由于log2(4)== 2,或者因为2 ^ 2 == 4,你需要两位,而不是三位。

您可能想要使用bit fields

答案 4 :(得分:0)

昨晚有discussion on the size allocated to bit-field structs。结构不能小于一个字节,并且大多数机器和编译器将是2或4,具体取决于编译器和字大小。所以,不,你不能得到一个3位结构(实际需要的2位)。但是,您可以将自己打包成一组数组,例如uint64_t。或者你可以创建一个包含16个2位成员的结构,看看gcc是否使它成为一个4字节的结构,然后使用它们的数组。

答案 5 :(得分:-1)

如果你已经拥有一些数据结构,有一个很老的伎俩可以偷偷摸摸几下。这是非常讨厌的,除非你有充分的理由,否则很可能根本不是一个好主意。我只是指出这一点,以防你真的需要保存几个位。

由于对齐,x86或x64上的指针通常是4的倍数,因此这些指针的两个最低有效位(例如指向int的指针)总是0。你可以利用这个并在那里偷偷摸摸你的两个位,但是你必须确保在访问这些指针时删除它们(取决于架构,我在这里不确定)。

同样,这是一个讨厌,危险和漂亮的UB,但也许在你的情况下是值得的。

答案 6 :(得分:-2)

3^5 = 243 

并且可以在8位中容纳5个条目。通过这种方式,您可以节省20%的空间来存储大量数据。您只需要查找表进行2次方向查找和操作。