【发布时间】:2016-04-16 19:06:22
【问题描述】:
试图将数据打包成一个数据包。此数据包应为 64 位。我有这个:
typedef union {
uint64_t raw;
struct {
unsigned int magic : 8;
unsigned int parity : 1;
unsigned int stype : 8;
unsigned int sid : 8;
unsigned int mlength : 31;
unsigned int message : 8;
} spacket;
} packet_t;
但似乎不能保证对齐。因为当我运行这个时:
#include <strings.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
const char *number_to_binary(uint64_t x)
{
static char b[65];
b[64] = '\0';
uint64_t z;
int w = 0;
for (z = 1; w < 64; z <<= 1, ++w)
{
b[w] = ((x & z) == z) ? '1' : '0';
}
return b;
}
int main(void)
{
packet_t ipacket;
bzero(&ipacket, sizeof(packet_t));
ipacket.spacket.magic = 255;
printf("%s\n", number_to_binary(ipacket.raw));
ipacket.spacket.parity = 1;
printf("%s\n", number_to_binary(ipacket.raw));
ipacket.spacket.stype = 255;
printf("%s\n", number_to_binary(ipacket.raw));
ipacket.spacket.sid = 255;
printf("%s\n", number_to_binary(ipacket.raw));
ipacket.spacket.mlength = 2147483647;
printf("%s\n", number_to_binary(ipacket.raw));
ipacket.spacket.message = 255;
printf("%s\n", number_to_binary(ipacket.raw));
}
我得到(大端):
1111111100000000000000000000000000000000000000000000000000000000
1111111110000000000000000000000000000000000000000000000000000000
1111111111111111100000000000000000000000000000000000000000000000
1111111111111111111111111000000000000000000000000000000000000000
1111111111111111111111111000000011111111111111111111111111111110
1111111111111111111111111000000011111111111111111111111111111110
我的 .mlength 字段在右侧某处丢失,但它应该就在 .sid 字段旁边。
This page 确认:包含位字段的分配单元的对齐方式未指定。但如果是这种情况,人们如何将数据打包到位字段的目的是什么?
24 位似乎是.mlength 字段在.message 字段被踢出之前能够采用的最大大小。
【问题讨论】:
-
通常,您不能依赖位域中的数据是如何布局的。如果您需要将多个数据打包成一个单词,则必须手动进行编组。
-
你的结构是 32 * 6 位...你应该使用字符来代替。
-
不要依赖于 C 数据结构的特定内存布局。定义的实现和特定于编译器的参数太多。正如@FUZxxl 所写,使用适当的编组。使用好的编译器,这不一定会变慢。
-
@xvan:使用标准类型是个坏主意。而
char更糟糕。 -
@Olaf 如果您知道自己在做什么,那么使用标准类型不是一个坏主意。
标签: c bit-fields