我需要在32位体系结构上处理一个包含8位位字段的结构体的字节顺序吗?

huangapple go评论75阅读模式
英文:

Do I need to handle endianess over an 8 bits bit-fields struct on a 32 bit architecture?

问题

我正在进行一些嵌入式软件开发,针对32位架构(精确地说是AVR32)。
在这个软件中,我从通过I2C连接的外部外设中检索一个以一个字节编码的标志。

这个字节的每个位都是一个布尔变量。
结构如下:

typedef union __attribute__((packed)){
  struct __attribute__((packed)) {
    uint8_t flag_a : 1;
    uint8_t flag_b : 1;
    uint8_t flag_c : 1;
    uint8_t flag_d : 1;
    uint8_t flag_e : 1;
    uint8_t __unused : 3;
  }
  uint8_t raw;
}Flag_t;

我的问题是,如果我想要使这段代码可移植,是否需要为另一种字节序重新定义联合内部的结构?

或者,这种情况下是否不存在字节序问题?

英文:

I am doing some embedded software on a 32 bits architecture (precisely AVR32).
On this software I am retrieving a flag, coded on one byte, from an external peripheral connected via I2C.

Each bits of this byte are a boolean variable.
The struct is the following:

typedef union __attribute__((packed)){
  struct __attribute__((packed)) {
    uint8_t flag_a : 1;
    uint8_t flag_b : 1;
    uint8_t flag_c : 1;
    uint8_t flag_d : 1;
    uint8_t flag_e : 1;
    uint8_t __unused : 3;
  }
  uint8_t raw;
}Flag_t;

My question is, if I want to make this code portable, do I need to redefine the struct inside the union in the reverse order for the other endianness ?

Or, is the endianness issues not present in this situation ?

答案1

得分: 3

大小端只对多字节变量有影响,所以在您的情况下不是问题。

然而,位域的使用可能会影响可移植性。C标准将其实现方式留给了编译器实现来决定。因此,不能期望它们在不同环境中表现相同。

一个更好的选择是简单地使用一个字节并定义不同位的含义。例如:

   typedef uint8_t Flag_t;
   typedef enum
   {
      flag_a = 1u << 0,
      flag_b = 1u << 1,
      flag_c = 1u << 2,
      flag_d = 1u << 3,
      flag_e = 1u << 4,
   } Flag_Bits_t;
英文:

Endianness is only an issue for multi-byte variables, so it is not an issue in your case.

However, the use of bit-fields is potentially an issue for portability. The C Standard leaves it up to the compiler implementation to decide how they are implemented. Thus they cannot be expected to behave identically across different environments.

A better option is simply to use a single byte and define the meaning of the different bits. E.g.:

   typedef uint8_t Flag_t;
   typedef enum
   {
      flag_a = 1u &lt;&lt; 0,
      flag_b = 1u &lt;&lt; 1,
      flag_c = 1u &lt;&lt; 2,
      flag d = 1u &lt;&lt; 3,
      flag e = 1u &lt;&lt; 4,
   } Flag_Bits_t;

答案2

得分: 3

Then do not use bit-fields. Use bit operations.

Yes, but this is compiler specific, i.e. not portable. On gcc you can use https://stackoverflow.com/questions/47600584/bitfield-endianness-in-gcc .

Yes, but not only - compiler may insert any padding between structure members, uint8_t may not be supported for a bitfield, and it is "endianness" of bits within a byte that compiler chooses to make.

英文:

> if I want to make this code portable

Then do not use bit-fields. Use bit operations.

> in the reverse order for the other endianness ?

Yes, but this is compiler specific, i.e. not portable. On gcc you can use https://stackoverflow.com/questions/47600584/bitfield-endianness-in-gcc .

> is the endianness issues not present in this situation ?

Yes, but not only - compiler may insert any padding between structure members, uint8_t may not be supported for a bitfield, and it is "endianness" of bits within a byte that compiler chooses to make.

huangapple
  • 本文由 发表于 2023年6月1日 15:45:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76379699.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定