协议是:
(four byte hour/minute/second field, for example (12:13:56 110))
bit00~bit01: 00
bit02~bit11: millisecond (110)
bit12~bit15: second-1s (6)
bit16~bit18: second-10s (5)
bit19~bit22: minute-1s (3)
bit23~bit25: minute-10s (1)
bit26~bit29: hour-1s (2)
bit30~bit31: hour-10s (1)
我应该如何定义上层结构?
我试图定义这个:
struct xxx_time
{
unsigned int pad:2;
unsigned int second0:4;
unsigned int second1:3;
unsigned int minute0:4;
unsigned int minute1:3;
unsigned int hour:4;
unsigned int hour1:2;
};
以这种方式定义它是否正确?还有更好的办法吗?
答案 0 :(得分:1)
我认为这很好,除了你忘记了毫秒级的场地。
struct xxx_time
{
unsigned int pad:2;
unsigned int milisecond:10;
unsigned int second0:4;
unsigned int second1:3;
unsigned int minute0:4;
unsigned int minute1:3;
unsigned int hour:4;
unsigned int hour1:2;
};
此外,如果pad
字段实际上仅用于填充(您不会操作它们),则可以使用未命名的字段:
struct xxx_time
{
unsigned int :2;
unsigned int milisecond:10;
//...
}
请记住,几乎所有关于位字段的内容都与实现有关。
答案 1 :(得分:1)
结构中位字段的内存布局是编译器定义的。无法保证编译器将按照列出的顺序布置结构字段。例如,pad字段可能不是struct中的前两位。请参阅Memory layout of struct having bitfields和Why bit endianness is an issue in bitfields?。
因此,您不能使用带有位字段的结构来映射已定义的底层内存布局。您必须使用位移和掩码来读取和写入具有给定内存布局的缓冲区。
答案 2 :(得分:0)
我认为这取决于您想要使用这些数据做什么。 数据结构的一个目标是更好或有效地存储和访问数据以服务于系统处理。
例如,如果你想知道并处理小时,分钟,你写的就可以了。如果你只关心整个时间,那么一次性变量就可以了。
这取决于您的要求如何使用这些数据。
答案 3 :(得分:0)
您的布局适用于最近的gcc编译器(以及兼容设备,例如icc)。
此外,对于大端机器,您需要“反转”结构:
struct xxx_time {
#ifdef WORDS_BIGENDIAN
unsigned int hour1:2;
unsigned int hour:4;
unsigned int minute1:3;
unsigned int minute0:4;
unsigned int second1:3;
unsigned int second0:4;
unsigned int milisecond:10;
unsigned int:2;
#else
...
#endif
};
关于实现定义行为的注释仍然适用,因此您应该检查编译器生成的内容。
看作C11(以及gnu99)允许匿名结构,这可以通过union轻松完成,不需要更改代码(只需要更改结构类型的声明):
union xxx_time_u {
uint32_t ival;
struct {
#ifdef WORDS_BIGENDIAN
unsigned int hour1:2;
...
#else
unsigned int:2
...
#endif
};
};