2010-04-19 62 views
4

首先,有问题的应用程序总是在同一个处理器上,编译器总是gcc,所以我不关心位域不可移植。如何获得位域以正确的顺序排列我的位?

gcc设置位域,使得第一个列出的字段对应于一个字节的最低有效位。所以下面的结构,具有一个 = 0,b = 1,Ç = 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 ++)

现在,让我们说,我想一个是一个六位整数。

现在,我可以看到为什么这是不行的,但我的编码结构如下:

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

设置bÇ,并d为1,一个为0导致以下两个字节:

c0 01 

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

e0 00 

有什么方法来指定在第一个字节的最显著位三位和六位跨越第一字节和五个最显著位的结构第二个最重要的位?

请注意,我无法控制这些位应该放在哪里:它是由别人的界面定义的位布局。

+0

“gcc列出位域,使得第一个列出的字段对应于一个字节的最低有效位。”不,GCC(在这种情况下包括'g ++',它继承C实现定义的行为)以ABI依赖的顺序列出位域:https://gcc.gnu.org/onlinedocs/gcc/Structures-unions-enumerations-和-bit-fields-implementation.html。无论这种情况发生在你的架构上,都是偶然的。 – 2016-01-05 13:38:18

回答

3

(请注意,所有这一切都是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); 

不过,我强烈建议你避免位域,而使用移动和口罩。

+0

我想你的意思是“注意小端”,而不是“不在小端”。不过,我想我明白你在说什么。在小端机器上,位的邻接由位如何打包成机器字决定,编译器假定机器字将要进行字节交换。 我会采取别人的建议,并做掩饰和转移,但感谢您找出这里发生了什么。 – 2010-04-19 02:52:04

+0

是 - gcc将*字*中的位字段从最低位封装到最高位 - 在小型机器上,最低8位存储在第一个字节中。 – caf 2010-04-19 05:46:28

3

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

我建议你只是掩盖和位运算工作了..

this link

主要使用位字段要么允许数据的严密包装或能指定一些外部生成的数据文件中的字段。 C不保证机器字内的字段的顺序,所以如果你使用它们是出于后面的原因,你的程序不仅是不可移植的,它也会依赖于编译器。该标准说,这些字段被打包成'存储单元',这通常是机器字。打包顺序以及位域是否可能跨越存储单元边界是实现定义的。要强制对齐存储单元边界,将在要对齐的位置之前使用零宽度字段。

1

C/C++具有由结构的位存储器布局指定位的无手段,所以你将需要做手动位从<stdint.h><cstdint>移位和屏蔽8位或16位(无符号)的整数(uint8_t,uint16_t )。我知道,在很多编程语言中,只有极少数人能够为位字段指定逐位存储器布局:Ada,Erlang,VHDL(和Verilog)。

(如果你想更多的语言添加到列表社区的wiki)

相关问题