如何获取位域以正确的顺序排列我的位?

发布于 2024-08-29 12:16:07 字数 934 浏览 1 评论 0原文

首先,相关应用程序始终位于同一处理器上,并且编译器始终为 gcc,因此我不担心位域不可移植。

gcc 布局位字段,使得第一个列出的字段对应于字节的最低有效位。因此以下结构,a=0,b=1,c=1,d=1,你得到一个字节值 e0。

struct Bits {
  unsigned int a:5;
  unsigned int b:1;
  unsigned int c:1;
  unsigned int d:1;
} __attribute__((__packed__));

(实际上,这是 C++,所以我说的是 g++。)

现在假设我希望 a 是一个六位整数。

现在,我明白为什么这不起作用,但我编写了以下结构:

struct Bits2 {
  unsigned int a:6;
  unsigned int b:1;
  unsigned int c:1;
  unsigned int d:1;
} __attribute__((__packed__));

bcd 设置为 1,和 a 到 0 会产生以下两个字节:

c0 01

这不是我想要的。我希望看到这一点:

e0 00

有没有办法指定一个结构,该结构在第一个字节的最高有效位中具有三位,并且在第一个字节的五个最低有效位和第二个字节的最高有效位中包含六个位?

请注意,我无法控制这些位的布局位置:它是由其他人的接口定义的位布局。

To begin with, the application in question is always going to be on the same processor, and the compiler is always gcc, so I'm not concerned about bitfields not being portable.

gcc lays out bitfields such that the first listed field corresponds to least significant bit of a byte. So the following structure, with a=0, b=1, c=1, d=1, you get a byte of value e0.

struct Bits {
  unsigned int a:5;
  unsigned int b:1;
  unsigned int c:1;
  unsigned int d:1;
} __attribute__((__packed__));

(Actually, this is C++, so I'm talking about g++.)

Now let's say I'd like a to be a six bit integer.

Now, I can see why this won't work, but I coded the following structure:

struct Bits2 {
  unsigned int a:6;
  unsigned int b:1;
  unsigned int c:1;
  unsigned int d:1;
} __attribute__((__packed__));

Setting b, c, and d to 1, and a to 0 results in the following two bytes:

c0 01

This isn't what I wanted. I was hoping to see this:

e0 00

Is there any way to specify a structure that has three bits in the most significant bits of the first byte and six bits spanning the five least significant bits of the first byte and the most significant bit of the second?

Please be aware that I have no control over where these bits are supposed to be laid out: it's a layout of bits that are defined by someone else's interface.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦屿孤独相伴 2024-09-05 12:16:07

(请注意,所有这些都是特定于 gcc 的注释 - 我很清楚位域的布局是实现定义的)。

不在小端机器上:问题在于,在小端机器上,第二个字节的最高有效位不被视为与第一个字节的最低有效位“相邻”。

不过,您可以将位域与 ntohs() 函数结合起来:

union u_Bits2{
    struct Bits2 {
      uint16_t _padding:7;
      uint16_t a:6;
      uint16_t b:1;
      uint16_t c:1;
      uint16_t d:1;
    } bits __attribute__((__packed__));
    uint16_t word;
}

union u_Bits2 flags;
flags.word = ntohs(flag_bytes_from_network);

但是,我强烈建议您避免使用位域,而使用移位和掩码。

(Note that all of this is gcc-specific commentary - I'm well aware that the layout of bitfields is implementation-defined).

Not on a little-endian machine: The problem is that on a little-endian machine, the most significant bit of the second byte isn't considered "adjacent" to the least significant bits of the first byte.

You can, however, combine the bitfields with the ntohs() function:

union u_Bits2{
    struct Bits2 {
      uint16_t _padding:7;
      uint16_t a:6;
      uint16_t b:1;
      uint16_t c:1;
      uint16_t d:1;
    } bits __attribute__((__packed__));
    uint16_t word;
}

union u_Bits2 flags;
flags.word = ntohs(flag_bytes_from_network);

However, I strongly recommend you avoid bitfields and instead use shifting and masks.

相思故 2024-09-05 12:16:07

通常,您无法对联合的打包方式做出强有力的假设,每个编译器实现都可能选择以不同的方式打包它(以节省空间或对齐字节内的位字段)。

我建议您只使用掩码和按位运算符。

来自 此链接

位域的主要用途是允许数据的紧密打包,或者能够指定一些外部生成的数据文件中的字段。 C 不保证机器字内字段的顺序,因此如果您出于后一个原因使用它们,您的程序不仅是不可移植的,而且还依赖于编译器。标准称字段被打包到“存储单元”中,这些单元通常是机器字。打包顺序以及位域是否可以跨越存储单元边界都是由实现定义的。要强制对齐存储单元边界,请在要对齐的字段之前使用零宽度字段。

Usually you can't do strong assumptions on how the union will be packed, every compiler implementation may choose to pack it differently (to save space or align bitfields inside bytes).

I would suggest you to just work out with masking and bitwise operators..

from this link:

The main use of bitfields is either to allow tight packing of data or to be able to specify the fields within some externally produced data files. C gives no guarantee of the ordering of fields within machine words, so if you do use them for the latter reason, you program will not only be non-portable, it will be compiler-dependent too. The Standard says that fields are packed into ‘storage units’, which are typically machine words. The packing order, and whether or not a bitfield may cross a storage unit boundary, are implementation defined. To force alignment to a storage unit boundary, a zero width field is used before the one that you want to have aligned.

执着的年纪 2024-09-05 12:16:07

C/C++ 无法指定结构体的逐位内存布局,因此您需要对 8 或 16 位(无符号)整数(来自 的 uint8_t、uint16_t 进行手动位移和屏蔽))。

在我所知道的十几种编程语言中,只有极少数允许您为位字段指定逐位内存布局:Ada、Erlang、VHDL(和 Verilog)。

(如果您想向该列表添加更多语言,请访问社区 wiki。)

C/C++ has no means of specifying the bit by bit memory layout of structs, so you will need to do manual bit shifting and masking on 8 or 16bit (unsigned) integers (uint8_t, uint16_t from <stdint.h> or <cstdint>).

Of the good dozen of programming languages I know, only very few allow you to specify bit-by-bit memory layout for bit fields: Ada, Erlang, VHDL (and Verilog).

(Community wiki if you want to add more languages to that list.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文