我有以下内存布局(伪代码):
struct {
union {
fieldA : 45;
struct {
fieldB1 : 12;
fieldB2 : 33;
}
}
fieldC : 19;
}
字符串
即,场A的存储器有时可用于其它目的(场B1和B2)。我希望这个结构体尽可能的压缩,即。64bit大小。
似乎无论我做什么(例如打包属性),联合总是在fieldC(当然也是填充的)之前填充3位以获得48位(6字节)。
4条答案
按热度按时间ccgok5k51#
如何用一个非常奇怪的位域排列构造一个C结构体/联合体?
64 bit大小。
使用一个typedef或一个结构体,其中包含一个
uint64_t
。使用位域操作为每个字段编写getter和setter。eaf3rand2#
作为一种可能的解决方法,您需要复制一些字段,并使用 all 字段创建两个结构的联合:
字符串
ulydmbyx3#
一般不使用位域。当然不是在您希望可移植的代码中。它们的语义定义比外行人所认为的要松散得多,而且它们在很多方面都令人惊讶。对于一些潜在用途重要的方面是未指定的或实现定义的,并且在实现之间确实变化。
然而,你可以依赖于除了位域之外的每个对象,使其具有由一个或多个(完整)字节组成的连续序列的表示(C23 6.2.6.1/2)。* 假设你的系统的字节是8位宽,你不能使
struct
或union
的表示正好包含45位,因为45不是8的倍数。在您的例子中,内部结构体的大小至少为 * 6个字节,因此包含它的联合体也必须至少有这么大。外部结构体包含一个需要19位的额外成员,因此整个结构体的大小必须至少为6 + 4 = 10字节。我的第一个建议是我的领导:不要使用位域。例如,在一个示例中,
字符串
当然,这并不能实现将其打包成64位的目标,但C并没有定义任何方法来确保结构或联合的这种打包。而且,这已经依赖于实现定义的行为,关于位域成员可能具有哪些类型说明符。
你可以考虑一个结构体的联合,比如@someprogrammerdude推荐的。但是只要64位就足够了,你也可以考虑一个普通的打包整数,也许有支持的宏或函数:
型
由于您表达了可能需要灵活处理数据结构更改的一些担忧,因此使用宏或函数 Package 访问并抽象数据类型可以提供很大的灵活性。
zpgglvta4#
在C编程语言的范围内,
struct
s和union
s实际上并不适合创建精确到位级别的内存布局。即使使用特定于编译器的 packing 扩展/杂注,您仍然可能最终会填充和对齐元素以满足实现的某些要求。在标准C中进行位级精确访问的唯一可靠方法是通过(数组)原语类型和位操作来屏蔽和提取/插入所需的值。然后还有整个endianess问题,我在这里懒得忽略它。在你的特殊情况下,你可以这样做:
字符串