使用结构时,通过联合转换类型不起作用
Converting types via unions doesn't work when using structs
我希望能够将字节“连接”在一起,这样如果我有字节 00101
和 010
,结果将是 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;
}
我做错了什么?联合应该让所有成员共享相同的内存,struct
和 long
正好占用 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
我希望能够将字节“连接”在一起,这样如果我有字节 00101
和 010
,结果将是 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;
}
我做错了什么?联合应该让所有成员共享相同的内存,struct
和 long
正好占用 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