2

我应该能够将一个值存储在一个可以从 0 到 3 的数据结构中。所以我需要 2 位。这个数据结构我会很大2^16个位置。所以,我想要 2 ^ 16 * 2(位)。在 C++ 中,您是否曾经在内存中恰好有 2 位?

4

7 回答 7

9

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

因此,您需要 astd::array<uint32_t, 4096>来容纳 2 16 个单位的 2 位值。

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

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>.

于 2011-11-26T15:33:43.867 回答
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
;

这些使用起来可能很笨拙,因为无法使用[]... 访问它们。最好的办法是创建自己的类,它的工作方式类似于 abitset但工作在 3 位而不是 1 位。

于 2011-11-26T15:34:05.447 回答
1

如果您不是在嵌入式系统上工作并且资源充足,您可以看看std::bitset<>哪个会使您作为程序员的工作更轻松。

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

于 2011-11-26T15:42:43.637 回答
0

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

您可能想要使用位域

于 2011-11-26T15:29:40.063 回答
0

昨晚讨论了分配给位域结构的大小。一个结构不能小于一个字节,并且对于大多数机器和编译器来说,它是 2 或 4,这取决于编译器和字长。所以,不,你不能得到一个 3 位结构(你实际需要的 2 位)。但是,您可以自己将位打包到一个数组中,例如uint64_ts。或者您可以创建一个具有 16 个 2 位成员的结构,并查看 gcc 是否将其设为 4 字节结构,然后使用这些成员的数组。

于 2011-11-26T15:41:10.973 回答
-1

如果您已经有一些数据结构,那么有一个非常古老的技巧可以偷偷摸摸。这是非常讨厌的,除非你有非常好的理由,否则它很可能根本不是一个好主意。我只是指出这一点,以防您真的需要节省一些位。

由于对齐,x86 或 x64 上的指针通常是 4 的倍数,因此此类指针(例如指向 的指针int)的两个最低有效位始终为0。您可以利用这一点并将您的两位潜入其中,但您必须确保在访问这些指针时删除它们(取决于架构,我不确定这里)。

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

于 2011-11-26T15:47:00.913 回答
-2
3^5 = 243 

并且可以在 8 位中容纳 5 个条目。以这种方式存储大量数据的空间减少了 20%。您所需要的只是用于 2 个方向查找和操作的查找表。

于 2011-11-26T15:49:52.130 回答