c – 比特压缩结构

我目前正在研究项目,我需要在向量中存储相当多的(〜十亿单位)结构.我还需要以线性方式迭代该向量,因此我必须通过的数据越少越好.

因此我自然而然地开始优化单一结构的尺寸.例如,如果我有多个bool值,我可以将true / false值存储在单个位中,并将所有bool值压缩为一个char / 16位,无论具有足够的大小.对于某些条目,我只需要20位无符号整数.因此我可以再次压缩这些值.

然后我最终得到这样的东西(注意这只是简化的例子):

class Foo {
private:
    uint32_t m_time;
    uint32_t m_comb;

public:
    Foo(uint32_t t, uint32_t big, uint16_t small, bool is_blue, bool is_nice)
        : m_time(t), m_comb((big << 12) | (small << 2) | (is_blue << 1) | is_nice)
    { }

    uint32_t get_time()  const { return m_time; }
    uint32_t get_big()   const { return m_comb >> 12; }
    uint16_t get_small() const { return m_comb & 0b11111111100; }
    uint16_t is_blue()   const { return m_comb & 0b10; }
    uint16_t is_nice()   const { return m_comb & 0b1; }
};

问题是,这可以通过某种方式使用模板自动化吗?我的想法是,我将插入条目的顺序,所需的位大小,而不是我能够调用get< i>(),这将返回我的第i个结构条目.我的动机是摆脱手动编写代码,因为在我看来,很容易出错.我试图实现这一点,但却无可救药地失败了.

最佳答案 您可以使用
bit fields轻松实现此功能.

class Foo {
private:
    uint32_t m_time;
    uint32_t m_big : 20;
    uint32_t m_small : 10;
    uint32_t m_isblue : 1;
    uint32_t m_isnice : 1;
public:
    Foo(uint32_t t, uint32_t big, uint16_t small, bool is_blue, bool is_nice)
        : m_time(t), m_big(big), m_small(small), m_isblue(is_blue), m_isnice(is_nice)
    { }

    uint32_t get_time()  const { return m_time; }
    uint32_t get_big()   const { return m_big; }
    uint16_t get_small() const { return m_small; }
    uint16_t is_blue()   const { return m_isblue; }
    uint16_t is_nice()   const { return m_isnice; }
};

Online demo显示尺寸.

编辑:其他信息

总结这些注释,编译器将位字段打包在一起的方式取决于实现:

9.6/1 (…) Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is
implementation-defined. Bit-fields are packed into some addressable
allocation unit. [Note: Bit-fields straddle allocation units on some
machines and not on others. Bit-fields are assigned right-to-left on
some machines, left-to-right on others. —end note ]

所以你不能保证,但编译器通常最好把它们放在一起.作为一个经验法则,只要您的位字段是连续的并且它们的总位小于您正在使用的基本类型,就很有可能打包最佳.如果需要,您可以微调基本类型,如this online demo所示.

点赞