0

协议是:

(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;
};

以这种方式定义它是否正确?有没有更好的办法?

4

4 回答 4

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;
    //...
}

请记住,几乎所有关于位域的内容都依赖于实现。

于 2013-07-16T02:42:52.017 回答
1

结构中位域的内存布局是编译器定义的。无法保证编译器会按照您列出的顺序排列结构字段。例如,填充字段可能不是结构中的前两位。请参阅具有位域的结构的内存布局为什么位字节序是位域中的问题?.

因此,不,您不能使用带有位字段的结构来映射定义的底层内存布局。您将不得不使用位移位和掩码来读取和写入具有给定内存布局的缓冲区。

于 2013-07-16T02:51:17.737 回答
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)允许匿名结构,这可以通过联合轻松完成,无需更改代码(只需更改具有 struct 类型的声明):

union xxx_time_u {
    uint32_t ival;
    struct {
#ifdef WORDS_BIGENDIAN
        unsigned int hour1:2;
        ...
#else
        unsigned int:2
        ...
#endif
    };
};
于 2013-07-16T04:03:18.140 回答
0

我认为这取决于您想使用这些数据做什么。数据结构的一个目标是更好或有效地存储和访问数据以服务于系统处理。

例如,如果您想知道并处理您所写的小时、分钟,就可以了。如果您只关心整个时间,那么一次性变量就可以了。

如何使用这些数据取决于您的要求。

于 2013-07-16T02:41:06.213 回答