联合和位域——它们是如何工作的?

Unions and bit fields — how do they work?

我在尝试理解这段代码时遇到了一些问题:

#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;

这是做什么用的?

假设 int 是 4 个字节,short 是 2 个字节,conversor 看起来像这样:

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

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

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

00000000000000000000000000001000

那么printf( "%d", conver.bin.valor );会输出第8位,也就是0。

然后 conver.entero <<= 1;entero 向左移动 1 位,结果是:

00000000000000000000000000010000

这会将未命名位字段的值乘以 2,valor 仍将为 0。这样做 8 次会将 entero 移位 8 位,并且在 i == 3 valor会"set"到1(因为你在shift之前输出,所以下一次迭代会输出结果)。

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

的第 8 位

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