C 获取位字段结构成员的大小

C 获取位字段结构成员的大小,c,bit-fields,C,Bit Fields,我定义了一个结构,如: struct mystruct { uint32_t onebyte : 8; uint32_t twobytes : 16; uint32_t threebits : 3; }; 我知道C将位字段定义为至少与指定的一样宽,但编译器可能会使用更多内存(例如,在本例中为3*4字节)。但是,设置的宽度是一个保证的最小值,如果某个值超过相应的范围,应用程序可能仍会碰巧正常工作 要运行一些调试断言,我希望我的代码在设置成员值之前检查值是否超出允

我定义了一个结构,如:

struct mystruct {
    uint32_t onebyte   :  8;
    uint32_t twobytes  : 16;
    uint32_t threebits :  3;
};
我知道C将位字段定义为至少与指定的一样宽,但编译器可能会使用更多内存(例如,在本例中为3*4字节)。但是,设置的宽度是一个保证的最小值,如果某个值超过相应的范围,应用程序可能仍会碰巧正常工作

要运行一些调试断言,我希望我的代码在设置成员值之前检查值是否超出允许的范围:

assert(someval < (1 << sizeofbitfieldmemberinbits(((mystruct*)NULL)->threebits)));
无论如何,有没有一种方法可以确定C结构的位字段成员的保证最小大小(以位为单位,或者至少以字节为单位)

我正在寻找一个类似于
sizeofbitfieldmemberinbits()
的表达式,它可以在编译时由编译器计算(类似于
((mystruct){.3bit=-1})。3bit
可以计算为
0x7

编辑: 正如John Bollinger所指出的,为位字段成员分配的内存可以大于指定的位数,但该成员所持有的值决不能大于
(1)
有没有办法确定C结构的位字段成员的保证最小大小(以位为单位)

我想检查这样的情况,在这种情况下,截断不仅可能发生,而且实际上发生了

assert()
不够,因为运行时不一定存在其相关代码

对照字段的最大值进行检查。当字段是某种无符号类型时,很容易做到这一点

有没有办法确定C结构的位字段成员的保证最小大小(以位为单位)

我想检查这样的情况,在这种情况下,截断不仅可能发生,而且实际上发生了

assert()
不够,因为运行时不一定存在其相关代码

对照字段的最大值进行检查。当字段是某种无符号类型时,很容易做到这一点

我正在寻找一个类似于
sizeofbitfieldmemberinbits()的表达式
可由编译器在生成时计算

您所描述的标准术语为“”:

可以在翻译过程中计算常量表达式,而不是 运行时,并相应地可用于常数可能存在的任何位置 是

(C2011,6.6/2)

接下来,您将阐明使用此类常量表达式的目的:

对于断言,我想检查这样的截断不存在的情况 可能会发生,但实际发生的时间

然而,请注意

  • 为此,位字段的大小是次要的。您实际需要的是最大的可表示值。对于有符号类型的位字段,您可能也需要最小值

  • 在您演示的常规断言(与静态断言相反)中使用常量表达式实际上并不需要。常规断言中的表达式在运行时进行计算

  • 另一方面,一些实现仍然可以在翻译(编译)时计算一些不满足标准中常量表达式定义的表达式

  • 第(2)和(3)点您很幸运,因为位字段具有不可直接表达的二级类型。在宿主结构对象的上下文之外,没有任何位字段类型的值,也没有可以表达位字段有效类型的类型名。这意味着没有计算为位字段成员的位数或最大值,除非它包含该成员的先验知识,因为结构(包括结构文字)不在可能出现在适当常量表达式中的操作数中:

    算术常数表达式应具有算术类型,且应 只有整数常量、浮点常量、, 枚举常量、字符常量、
    sizeof
    表达式 结果是整数常量和表达式的对齐。强制转换 算术常数表达式中的运算符只能转换为 算术类型到算术类型,但作为操作数的一部分到 操作员的
    sizeof
    \u校准

    ()


    在所有这些之后,我认为问题真的可以归结为:

    我不确定这是否保证有效:

    assert(someveal <= ((mystruct){.threebits = -1}).threebits);
    
    assert(someveal <= ((mystruct){.threebits = -1}).threebits);
    
    …然后与其成员进行比较:

    assert(someveal <= mystruct_limits.threebits);
    
    assert(someveal)
    我正在寻找一个类似于
    sizeofbitfieldmemberinbits()的表达式
    可由编译器在生成时计算

    您所描述的标准术语为“”:

    可以在翻译过程中计算常量表达式,而不是 运行时,并相应地可用于常数可能存在的任何位置 是

    (C2011,6.6/2)

    接下来,您将阐明使用此类常量表达式的目的:

    对于断言,我想检查这样的截断不存在的情况 可能会发生,但实际发生的时间

    然而,请注意

  • 为此,位字段的大小是次要的。您实际需要的是最大的可表示值。对于有符号类型的位字段,您可能也需要最小值

  • 在您演示的常规断言(与静态断言相反)中使用常量表达式实际上并不需要。常规断言中的表达式在运行时进行计算

  • 另一方面,一些实现仍然可以在翻译(编译)时计算一些不满足标准中常量表达式定义的表达式

  • 第(2)点和第(3)点对您来说是幸运的,因为位字段具有不可直接表达的二级类型。在宿主结构对象的上下文之外,没有任何位字段类型的值,也没有可以表达位字段有效类型的类型名
    assert(someveal <= ((mystruct){.threebits = -1}).threebits);
    
    static const struct mystruct mystruct_limits = { -1, -1, -1 };
    
    assert(someveal <= mystruct_limits.threebits);