我有一个看起来像这样的结构:

#include <stdint.h>

struct bits {
    uint8_t u_     : 1;
    uint8_t k_     : 1;
    uint8_t c_     : 1;

    uint8_t x_     : 1;
    uint8_t b_     : 1;

    uint8_t ns_    : 1;
    uint8_t ms_    : 1;
    uint8_t as_    : 1;
    uint8_t /*padding1*/ : 0;

    uint8_t st_    : 3;
    uint8_t su_    : 1;
    uint8_t ig_    : 1;

    uint8_t h_     : 1;
    uint8_t in_    : 1;

    uint8_t pad2_  : 1;

    bits_t(uint8_t u, uint8_t k, uint8_t c, uint8_t x, uint8_t b,
           uint8_t n, uint8_t m, uint8_t a, uint8_t s, uint8_t i,
           bool h, bool in)
       : u_    { u }
       , k_    { k }
       , c_    { c }
       , x_    { x }
       , b_    { b }
       , ns_   { n }
       , ms_   { m }
       , as_   { a }
       , st_   { 0 }
       , su_   { s }
       , ig_   { i }
       , h_    { h }
       , in_   { in }
       , pad2_ { 0 } // carefully initialize all bits
    {}
};


这些结构的operator==使用memcmp,因此在构造函数中将所有位都设置为已知值非常重要。

最近,我意识到h_in_在做相同的事情,除了相反的事情,即assert(h_ == !in_)始终成立。我将要删除h_,并且我想进行一些编译时检查,以警告我pad2_需要从: 1扩展到: 2

这可能吗?我什么也没想(带或不带sizeof(bits)字段的h_都是一样的)。

最佳答案

因此,无法查询位域的偏移量。因此,将很难在位域上创建任何约束。尽管以下预处理技巧可以帮助您实现所需的目标。

您本质上需要做的是使用宏创建结构字段。

带有2位字段的普通结构可以如下所示

#define STRUCT_NAME my_bitfield
#define FIELD_LIST \
     FIELD(a,3) \
     FIELD(b,5)

#define FIELD(x,y) int x:y;
struct STRUCT_NAME {
     FIELD_LIST
};


到目前为止一切都很好。现在我们要做的是创建一个辅助struxt,它具有并行元素,但是每个元素都是n个字节

#undef FIELD
#define FIELD(x,y) char x[y];
struct aux_##STRUCT_NAME {
    FIELD_LIST
};


凉。现在我们有了优势。我们可以使用此辅助结构的sizeof并检查它是否为8的倍数

static_assert(sizeof(struct aux_##STRUCT_NAME) % 8 == 0);


现在,这将自动检查您的位域结构是否具有足够的位填充。

最后,要重新使用此代码,您可以在.h文件和您的主代码中添加实际的生成代码,只需重新定义FIELD_LISTSTRUCT_NAME并包含标头即可。

关于c++ - 如何检查位域是否覆盖所有位,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45820955/

10-11 17:57