【问题标题】:C++ How can i fill the bit fields of a struct from a uchar array?C++ 如何从 uchar 数组中填充结构的位字段?
【发布时间】:2017-05-04 09:52:34
【问题描述】:

我有一个 unsigned char 数组,其值如下:

u_char *t_header[4]; //filled with values 0x00000047,0x00000004,0x00000093,0x00000012

我有一个结构如下:

            #pragma pack(push, 1)
            typedef struct th_struct {
                unsigned s_byte : 8;
                unsigned t_e_indicator : 1;
                unsigned p_u_s_indicator : 1;
                unsigned t_priority : 1;
                unsigned id : 13;
                unsigned t_s_control : 2;
                unsigned a_f_control : 2;
                unsigned c_counter : 4; 
            }th_struct;
            #pragma pack(pop)

我正在尝试填写以下结构字段:

            const struct  th_struct *tsh;
            tsh = (struct th_struct*)(t_header);

它按预期用十六进制的71 = 0x47 填充tsh->s_byte,但其余字段均为0

我必须做些什么才能用u_char *t_header[4] 值正确填充struct th_struct *tsh,如下所示?

0100 0111 .... .... .... .... .... .... = (0x00000047) tsh->s_byte .... .... 0... .... .... .... .... .... = 0 tsh->t_e_indicator .... .... .0.. .... .... .... .... .... = 0 tsh->p_u_s_indicator .... .... ..0. .... .... .... .... .... = 0 tsh->t_priority .... .... ...0 0100 1001 0011 .... .... = (0x00000493) tsh->id .... .... .... .... .... .... 00.. .... = (0x00000000) tsh->t_s_control .... .... .... .... .... .... ..01 .... = (0x00000001) tsh->a_f_control .... .... .... .... .... .... .... 0010 = 2 tsh->c_counter

谢谢!

【问题讨论】:

  • 首先这真的取决于你平台的字节序...
  • 1) 您没有 uchar 数组 2) 您不能通过将某些内容分配给指向结构的指针来填充结构。请展示一个完整的代码示例。
  • sizeof(th_struct) = 4sizeof(t_header) = 32
  • 第二个 u_char *t_header[4]; 可能是 32 字节,不适合 32 位 结构....
  • 感谢您的回答。我看到sizeof(th_struct) = 4 and sizeof(t_header) = 32 不一样。我想我必须将 t_header 数组转换为 4 个字节的东西,例如 0x47049312 但如何?

标签: c++ c arrays struct binary


【解决方案1】:

首先你有一个问题:

u_char *t_header[4];

那是 4 个指针 - 而不是 4 个 u_char。你可能想要:

u_char t_header[4];

下一个问题是位域的布局依赖于实现。

因此,(通常)编写假定特定布局的代码是一个坏主意。这样的代码将只能在编写代码时使用的特定系统上运行,即代码是不可移植的。

我建议您使用移位运算符>> 和按位运算符& 来准确选择所需的位:

unsigned char t_header[4] = {0x47, 0x04, 0x93, 0x12};
th_struct tsh;

tsh.s_byte = t_header[0];
tsh.t_e_indicator = (t_header[1] >> 7) & 0x1;
tsh.p_u_s_indicator = (t_header[1] >> 6) & 0x1;
tsh.t_priority = (t_header[1] >> 5) & 0x1;
tsh.id = ((unsigned)(t_header[1] & 0x1f) << 8) + t_header[2];
tsh.t_s_control = (t_header[3] >> 6) & 0x3;
tsh.a_f_control = (t_header[3] >> 4) & 0x3;
tsh.c_counter = t_header[3] & 0xf;

printf("s_byte=%x\n", tsh.s_byte);
printf("t_e_indicator=%x\n", tsh.t_e_indicator);
printf("p_u_s_indicator=%x\n", tsh.p_u_s_indicator);
printf("t_priority=%x\n", tsh.t_priority);
printf("id=%x\n", tsh.id);
printf("t_s_control=%x\n", tsh.t_s_control);
printf("a_f_control=%x\n", tsh.a_f_control);
printf("c_counter=%x\n", tsh.c_counter);

那么你也可以避免使用打包的结构。

【讨论】:

  • 我假设@swartkatt 知道这不会是可移植的,但无论如何提及它是个好主意。看来他们正在做一些非常特定于平台的事情,可能与硬件相关。
  • 非常感谢您的帮助!
【解决方案2】:

你可以这样做:

struct  th_struct t_header = {
    .s_byte = 0x47,
    .t_e_indicator = 0,
    .p_u_s_indicator = 0,
    .t_priority = 0,
    .id = 0x00000493,
    .t_s_control = 0,
    .a_f_control = 1,
    .c_counter = 2 };

然后: const struct th_struct* tsh = &amp;t_header;

我认为这更容易。

你必须像这样改变你对某事的评价方式:

u_char t_header[4];
t_header[0] = 0x47;     // s_byte
t_header[1] = (u_char)
        (0x00           // t_e_indicator
         | (0x00 << 1)  // p_u_s_indicator
         | (0x00 << 2)  // t_priority
         | (0x493 << 3)); // id[0..4]
t_header[2] = (u_char) ((0x493 << 3) >> 8); // id [5..12]
t_header[3] = (u_char)
        (0x00           // t_s_control
        | (0x01 << 2)   // a_f_control
        | (0x02 << 4)); // c_counter

const struct th_struct* tsh = (th_struct*)t_header;

或者改变结构顺序:

#pragma pack(push, 1)
           typedef struct th_struct2 {
               unsigned s_byte : 8;
               unsigned id1 : 5;
               unsigned t_e_indicator : 1;
               unsigned t_priority : 1;
               unsigned p_u_s_indicator : 1;
               unsigned id2 : 8;
               unsigned c_counter : 4;
               unsigned a_f_control : 2;
               unsigned t_s_control : 2;
           }th_struct2;
           #pragma pack(pop)

其中 id1 是 od id 的较高部分,id2 是较低的部分。

【讨论】:

  • 谢谢,但我需要从uchar t_header[4] 数组中分配值。这些值不是固定的,而是在变化的。
  • @swartkatt 可以是uchar t_header[4]吗?还是必须是uchar *t_header[4]
  • 正如你和 4386427 告诉我的,uchar *t_header[4] 的大小不等于 4,因此我认为它必须是 uchar t_header[4]。我发现了一个与我的情况类似的示例,如下users.cs.cf.ac.uk/Dave.Marshall/C/node13.html#fig:drive,但为什么我的示例不起作用?
  • 我一次只能访问 1 个字节。因此,为了达到 4 个字节,我想创建一个数组并将 4 个字节存储到该数组中。在它达到 4 个字节后,我需要将其拆分为 th_struct 的结构中的位,以访问结构值以供 tsh-&gt;s_byte 以后使用......任何可以完成任务的想法都被接受。谢谢!
  • 我有一个const u_char *pkt_data,长度为1358,我通过如下的for循环到达每个字节:for (int i = 0; i &lt; 5; i++) t_header[i] = pkt_data[i];,我应该用这个循环或这个t_header[4]数组做点什么。谢谢
猜你喜欢
  • 2018-06-30
  • 2015-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多