2
#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");
}

在这个问题中,联合的大小将不同于为联合分配的位字段数。谁能解释其中的区别..以及剩余的内存会发生什么?

4

3 回答 3

5

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

实现可以分配任何大到足以容纳位字段的可寻址存储单元。

由于这是 a union,并且联合中的所有成员仅使用来自 a 的不超过 3 位unsigned int,因此 the 的大小union将至少为 if 的大小char,加上系统要求的填充(如果有)。在许多系统上,它会将每个单元填充到位字段所针对的类型的大小,所以在这种情况下,我希望 的大小union与 an 的大小相同unsigned int(尽管这可能是由于union无论如何都要满足正常的填充要求)。

大小的0位字段在 a 中是一个红鲱鱼union,但它在 a 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将至少为 2char秒(如果需要,加上任何其他填充)。大多数时候,它实际上会达到 2unsigned int秒的大小。

于 2013-07-18T20:46:14.953 回答
1

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

为简单起见,假设字长为 8,并且您在联合中使用 2 和 3 的位域。我用字母来表示各个位。

a b c d e f g h

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

可以更好地解释它。

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

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

于 2013-07-18T20:42:36.420 回答
0

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

所以“a”指的是第一个(就在第零位旁边:-)位,“b”指的是前三位,“d”和“e”都指的是同一个 32 位的第一位(4字节)字。

于 2013-07-18T20:29:37.947 回答