位字段和联合大小

时间:2013-07-18 20:14:24

标签: c

#include<stdio.h>
main()
{
    union d
    {
        unsigned int a:1;
        unsigned int b:3;
        unsigned :0;
        unsigned int d:1;
        unsigned int e:1;
    };
    union d aa;
    aa.b=9;
    printf("d.aa.a=%d d.aa.b=%d",aa.a, aa.b);
system("pause");
}

在这个问题中,union的大小与为union分配的bit字段的数量不同。任何人都可以解释这个区别......剩下的内存会发生什么?

3 个答案:

答案 0 :(得分:5)

关于包含位域的类型的大小,标准说(C11 6.7.2.1 p11):

  

实现可以分配足够大的任何可寻址存储单元来保存位字段。

由于这是union,并且联合中的所有成员仅使用unsigned int中不超过3位,union的大小至少为char大小如果union,加上系统要求的填充(如果有的话)。在许多系统上,它会将每个单元填充到比特字段所采用的类型的大小,因此在这种情况下,我希望unsigned int的大小与{{的大小相同1}}(尽管这可能是由于正常的union填充要求而发生的。)

0大小的位字段是union中的红鲱鱼,但它在struct(C11 6.7.2.1 p12)中具有特殊含义:

  

没有声明符但只有冒号和宽度的位字段声明表示   未命名的位域。作为特殊情况,宽度为0的位域结构成员   表示不会将其他位字段打包到放置了前一位字段(如果有)的单元中。

因此,如果您的union改为struct

struct d
{
    unsigned int a:1;
    unsigned int b:3;
    unsigned :0;
    unsigned int d:1;
    unsigned int e:1;
};

然后,此struct的大小至少为2 char s(如果需要,还有任何其他填充)。大多数情况下,它实际上会达到2 unsigned int s的大小。

答案 1 :(得分:1)

计算机体系结构具有一定的字长。虽然如果正确使用,声明位字段可能是有效的,但如果字长是可变的则不会有效。我认为大多数编译器会出于效率原因填充位。简而言之,在大多数情况下,其余的位将丢失。

为简单起见,假设字长为8,并且在并集中使用2和3的位字段。我用字母来表示个别位。

a b c d e f g h

在我的示例中将使用前3位a,b和c,编译器将确保不使用其余位。

This可以用更好的词语来解释。

但是,在联盟中使用位字段?我不确定这是个好主意。

希望我的解释有所帮助。有疑问吗?

答案 2 :(得分:0)

面团!大小将填充到4个字节(在大多数实现中)

所以“a”指的是第一个(紧挨着第0位:-)位,“b”指前三位,“d”和“e”都指第一位所有的相同的32位(4字节)字。