【问题标题】:Defining custom time structure定义自定义时间结构
【发布时间】:2013-07-16 13:00:13
【问题描述】:

协议是:

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

这样定义合适吗?有没有更好的办法?

【问题讨论】:

    标签: c linux


    【解决方案1】:

    结构中位域的内存布局是编译器定义的。无法保证编译器会按照您列出的顺序排列结构字段。例如,填充字段可能不是结构中的前两位。请参阅Memory layout of struct having bitfieldsWhy bit endianness is an issue in bitfields?

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

    【讨论】:

      【解决方案2】:

      我认为这很好,只是你忘记了毫秒字段。

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

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

      【讨论】:

      • " :2; "不能编译,应该是" unsigned int :2;"??
      • @user2585549 对,类型还是要的,修好了。
      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

        您的布局将适用于最近的 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 xxx_time_u {
            uint32_t ival;
            struct {
        #ifdef WORDS_BIGENDIAN
                unsigned int hour1:2;
                ...
        #else
                unsigned int:2
                ...
        #endif
            };
        };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-10-06
          • 1970-01-01
          • 1970-01-01
          • 2018-06-01
          • 2010-10-09
          • 2016-02-07
          • 2020-04-15
          相关资源
          最近更新 更多