工会和位域 - 它们如何工作?

时间:2015-04-11 23:02:55

标签: c unions bit-fields

尝试理解此代码时遇到一些问题:

#include <stdio.h>

typedef union
{
    int entero;
    struct
    {
        unsigned short : 7;
        unsigned short valor: 1;
    } bin;
} conversor;

int main(void)
{
    int numero = 8, i;
    conversor conver;
    conver.entero = numero;

    for ( i = 0; i < 8; i++ )
    {
        printf( "%d", conver.bin.valor );
        conver.entero <<= 1;
    }
    printf( "\n" );

    return 0;
}

如果某人愿意解释这段代码如何将整数转换为二进制,那么会以联盟的每个成员为例。

unsigned short : 7;

这是为了什么?

1 个答案:

答案 0 :(得分:1)

假设int为4个字节且short为2,conversor将如下所示:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // <- conversor union
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // <- int entero
                XXXXXXXXXXXXXXXX // <- struct bin
                         XXXXXXX // <- anonymous field
                        X        // <- valor
                XXXXXXXX         // <- unused space from bin

union会将所有成员塞入同一地址,并与其最大成员一样大。位字段将使用按位运算将字段打包为单个位,用户可以明确指定宽度。

您的代码将entero设置为8,如下所示:

00000000000000000000000000001000

然后printf( "%d", conver.bin.valor );将输出第8位,即零。

然后conver.entero <<= 1;会将entero向左移1位,结果如下:

00000000000000000000000000010000

这会将未命名位字段的值乘以2,valor仍然为0.这样做8次会将entero移动8位,而i == 3 valor将会{被“设置”为1(因为你在移位前输出,结果将在下一次迭代中输出。)

在这种情况下,未命名的位字段用作7位填充,因此valor对应于struct的第8位。

另请注意,该标准并未强制执行位字段的特定实现,但通常它们遵循常识。