如何更改结构的字节顺序?

时间:2020-10-19 10:35:32

标签: c++ c embedded-linux

如何更改C或C ++中压缩结构的顺序?

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="./src/styles.css" />
  </head>

  <body>
    <div class="img-container">
      <div class="crousel">
        <input type="radio" name="button" id="toggle1" class="toggle-button" />
        <input type="radio" name="button" id="toggle2" class="toggle-button" />
        <input type="radio" name="button" id="toggle3" class="toggle-button" />

        <img
          src="https://cdn.pixabay.com/photo/2020/10/06/11/50/dog-5632005__340.jpg"
          alt=""
          class="box"
        />
        <img
          src="https://cdn.pixabay.com/photo/2020/09/12/09/26/gorilla-5565295__340.jpg"
          alt=""
          class="box"
        />
        <img
          src="https://cdn.pixabay.com/photo/2020/09/14/17/19/beach-5571545__340.jpg"
          alt=""
          class="box"
        />
      </div>
    </div>
    <div class="buttons">
      <label for="toggle1">1</label>
      <label for="toggle2">2</label>
      <label for="toggle3">3</label>
    </div>
  </body>
</html>

结构(或LSB)的地址0x0为struct myStruct { uint32_t A; uint16_t B1; uint16_t B2; } __attribute__((packed));

我的应用程序与硬件通信,并且硬件中的结构定义如下:

A

但是在SystemVerilog中,“地址0x0”或更准确地说是结构的LSB是struct packed { logic [31:0] A; logic [15:0] B1; logic [15:0] B2; } myStruct;

顺序相反。

为了保持一致并避免更改硬件部分,我想反转整个C / C ++结构的“字节序”。

我可以反转所有字段:

LSB of B2  = B2[0]

但是它容易出错,而且不太方便。

对于数据类型,SystemVerilog和Intel CPU都是低位优先的,这不是问题。

  • 我该怎么办?

3 个答案:

答案 0 :(得分:2)

如何更改结构的字节顺序?

您不能更改成员中字节的顺序。并且您不能将成员相对于其他成员的内存顺序更改为不同于其声明顺序。

但是,您可以更改成员的声明顺序,这决定了成员的存储顺序。第一个成员始终位于最低内存位置,第二个成员位于此位置之后,依此类推。

如果可以根据verilog源知道正确的成员顺序,则理想情况下应使用元编程生成C结构定义,以确保匹配顺序。

容易出错

依靠特定的内存顺序确实容易出错。

可能仅依赖于源数据的已知存储顺序(大概是字节数组),而完全不依赖于成员的存储顺序:

unsigned char* data = read_hardware();
myStruct s;
s.B2 = data[0] << 0u
     | data[1] << 8u;
s.B1 = data[2] << 0u
     | data[3] << 8u;
s.A  = data[4] << 0u
     | data[5] << 8u
     | data[6] << 16u
     | data[7] << 24u;

这既不依赖于成员的内存布局,也不依赖于CPU的字节顺序。它仅取决于源数据的顺序(在这种情况下,假定为小端)。

如果可能的话,理想情况下,也应该根据Verilog源生成此函数。

答案 1 :(得分:1)

如何更改C或C ++中压缩结构的顺序?

C指定将结构的成员按声明的顺序排列在内存中,并在转换为适当的指针类型时声明 first 的地址,等于整个结构的地址。至少对于用C表示的结构类型(例如您的结构类型),符合C ++的实现将遵循相同的成员顺序规则。支持打包结构布局作为扩展的那些实现在它们的含义上是非常一致的:打包结构布局将在成员之间没有填充,并且总大小是成员大小的总和。而且没有其他效果。

我不知道有任何实现提供扩展的实现,该扩展允许成员的声明顺序与声明顺序不同,谁愿意执行该扩展?成员的顺序是明确定义的。如果要更改顺序,则解决方案是更改成员的声明顺序。

如果VeriLog确实确实以不同的方式命令成员(我无法与之交谈),那么我认为您只需要为此与他人保持和平。根据您的需要或最有意义的方式实施它,在两侧记录并继续前进。我倾向于认为,曾经注意到两种语言的声明顺序不同的人数将会很少。只要有适当的文档,那些注意到的文档都不会倾向于认为有错误。

答案 2 :(得分:0)

您知道我只是在使用AMD的开源驱动程序来处理字节序。

首先,他们使用cmake检测系统是大端还是小端。

#if !defined (__GFX10_GB_REG_H__)
#define __GFX10_GB_REG_H__

/*
*    gfx10_gb_reg.h
*
*    Register Spec Release:  1.0
*
*/

//
// Make sure the necessary endian defines are there.
//
#if defined(LITTLEENDIAN_CPU)
#elif defined(BIGENDIAN_CPU)
#else
#error "BIGENDIAN_CPU or LITTLEENDIAN_CPU must be defined"
#endif

union GB_ADDR_CONFIG
{
    struct
    {
#if defined(LITTLEENDIAN_CPU)
        unsigned int                       NUM_PIPES : 3;
        unsigned int            PIPE_INTERLEAVE_SIZE : 3;
        unsigned int            MAX_COMPRESSED_FRAGS : 2;
        unsigned int                       NUM_PKRS  : 3;
        unsigned int                                 : 21;
#elif defined(BIGENDIAN_CPU)
        unsigned int                                 : 21;
        unsigned int                       NUM_PKRS  : 3;
        unsigned int            MAX_COMPRESSED_FRAGS : 2;
        unsigned int            PIPE_INTERLEAVE_SIZE : 3;
        unsigned int                       NUM_PIPES : 3;
#endif
    } bitfields, bits;
    unsigned int    u32All;
    int             i32All;
    float           f32All;
};

#endif

是的,如上所述有一些代码重复。但是我也没有一个普遍更好的解决方案。