使用结构时,通过联合转换类型不起作用

Converting types via unions doesn't work when using structs

我希望能够将字节“连接”在一起,这样如果我有字节 00101010,结果将是 00101010

为此任务我编写了以下代码:

#include <stdio.h>
typedef struct
{
    unsigned char bits0to5 : 6;
    unsigned char bits5to11 : 6;
    unsigned char bits11to15 : 4;
}foo;
typedef union
{
    foo bytes_in_one_form;
    long bytes_in_other_form : 16;
}bar;
int main()
{
    bar example;
    /*just in case the problem is that bytes_in_other_form wasn't initialized */
    example.bytes_in_other_form = 0;
    /*001000 = 8, 000101 = 5, 1111 = 15*/
    example.bytes_in_one_form.bits0to5 = 8;
    example.bytes_in_one_form.bits5to11 = 5;
    example.bytes_in_one_form.bits11to15 = 15;
    /*sould be 0010000001011111 = 8287*/
    /*NOTE: maybe the printf is wrong since its only 2 bytes and from type long?*/
    printf("%d", example.bytes_in_other_form); 
    /*but number printed is 1288*/
    return 0;
}

我做错了什么?联合应该让所有成员共享相同的内存,structlong 正好占用 2 个字节。

注:

对于使用完全不同算法的解决方案,请注意我需要能够在开头使用零(因此例如 8 = 001000 而不是 1000,并且解决方案应该匹配任何任何分布的字节数(尽管了解我在当前算法中做错了什么更好)我还应该提到我使用 ANSI C.

谢谢!

此答案适用于原始问题,该问题具有:

typedef struct
{
    unsigned char bits0to5 : 6;
    unsigned char bits5to11 : 6;
    unsigned char bits11to15 : 4;
}foo;

这是您的特定示例中发生的情况(请注意,结果可能因平台而异):

位字段被打包到 char 变量中。如果下一个位域不适合当前 char,它会跳到下一个。此外,您有小端寻址,因此 char 值在别名 long 位字段中从右到左显示。

所以结构字段的布局是:

+--------+--------+--------+
|....cccc|..bbbbbb|..aaaaaa|
+--------+--------+--------+

其中aaaaaa为第一个字段,bbbbbb为第二个字段,cccc为第三个字段,.值为padding。

存储您的值时,您有:

+--------+--------+--------+
|....1111|..000101|..001000|
+--------+--------+--------+

填充位中有零,这变成:

+--------+--------+--------+
|00001111|00000101|00001000|
+--------+--------+--------+

联合中的另一个值别名到低位 16 位,因此它提取的值是:

+--------+--------+
|00000101|00001000|
+--------+--------+

这是 0x0508,如您所见,十进制是 1288

如果结构改为使用 unsigned long 作为位字段类型,那么我们有:

typedef struct
{
    unsigned long bits0to5 : 6;
    unsigned long bits5to11 : 6;
    unsigned long bits11to15 : 4;
}foo;

在这种情况下,字段被打包到一个 unsigned long 中,如下所示:

    -----+--------+--------+
    .....|11110001|01001000|
    -----+--------+--------+

低16位为0xf148,十进制为61768