C结构元素对齐(ansi)
C struct elements alignment (ansi)
只是一个简单的问题。。。标准对结构构件对齐有何规定?例如这个:
struct
{
uint8_t a;
uint8_t b;
/* other members */
} test;
是否保证b位于结构起点的偏移量1处?感谢
标准(从C99开始)并没有真正说明什么。
唯一真正的保证是(void *)&test == (void *)&a
和a
位于比b
更低的地址。其他一切都取决于实施。
C11 6.7.2.1结构和并集说明符p14表示
结构或并集对象的每个非位字段成员都在适用于其类型的实现定义的方式。
意味着您不能对a
和b
的地址之间的差异进行任何可移植的假设。
应该可以使用offsetof来确定成员的偏移量。
对于C,对齐是实现定义的,我们可以在C99标准草案6.7.2.1
结构和并集说明符第12段(在C11中,它将是第14段)中看到:
结构或联合对象的每个非位字段成员都以适合其类型的实现定义的方式对齐。
和段落13说:
在结构对象中,非位字段成员和位字段所在的单位resident的地址按声明的顺序增加。指向经过适当转换的结构对象指向其初始成员(或者如果该成员是位字段,然后到它所在的单元),反之亦然。可能有未命名的在结构对象中填充,但不在其开头。
对于C++,我们从标准草案9.2
类成员第13段中有以下类似的引用:
具有相同访问控制(第11条)的(非并集)类的非静态数据成员被分配,以便稍后的成员在类对象中具有更高的地址。具有不同访问控制的非静态数据成员的分配顺序未明确(第11条)。实施一致性要求可能会导致两个相邻成员不能立即相互分配;
和段落19说:
一个指向标准布局结构对象的指针,该对象使用interpret_cast进行了适当转换,指向其初始成员(或者,如果该成员是位字段,则为其所在的单元),反之亦然。[注:因此,在标准布局结构对象中可能存在未命名的填充,但不是在其开头,以实现适当的对准--尾注]
您使用的大小写并不是真正的边缘大小写,两个uint_8都足够小,可以放在内存中的同一个单词中,将每个uint-8放在uint_16中是没有用的。
一个更关键的情况是:
{
uint8_t a;
uint8_t b;
uint_32 c; // where is C, at &a+2 or &a+4 ?
/* other members */
} test;
无论如何,这将始终取决于目标体系结构和编译器。。。
K&R第二版(ANSI C)第6.4章(第138页)说:
然而,不要假设结构的大小是其成员大小的总和。由于不同对象的对齐要求,结构中可能存在未命名的"孔"。
因此,ANSI C不保证b
处于偏移量1。
编译器甚至可能将b
放在偏移量sizeof(int)
处,这样它就可以根据机器字的大小对齐,这更容易处理。
有些编译器支持pack pragma,这样您就可以强制struct
中没有这样的"漏洞",但这是不可移植的。
其他答案已经提到了C标准所保证的内容。
但是,为了确保b
在偏移量1
处,编译器可能会提供"打包"结构的选项,即显式添加无填充。
对于gcc,这可以通过#pragma
pack()
来实现。
#pragma pack(1)
struct
{
uint8_t a; /* Guaranteed to be at offset 0. */
uint8_t b; /* Guaranteed to be at offset 1. */
/* other members are guaranteed to start at offset 2. */
} test_packed;
#pragma pack()
struct
{
uint8_t a; /* Guaranteed to by at offset 0. */
uint8_t b; /* NOT guaranteed to be at offset 1. */
/* other members are NOT guaranteed to start at offset 2. */
} test_unpacked;
一个可移植(和保存)的解决方案是简单地使用一个数组:
struct
{
uint8_t ab[2]; /* ab[0] is guaranteed to be at offset 0. */
/* ab[1] is guaranteed to be at offset 1. */
/* other members are NOT guaranteed to start at offset 2. */
} test_packed;
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 如何创建一个QTableWidgetItem,用长文本右对齐,左边有省略号
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 64位机器上的C++内存对齐
- 为什么我可以将变量存储在不是其最小对齐方式的倍数的地址?
- 使 std::vector 分配对齐内存的现代方法
- C++ cout 将双精度对齐到精度 2 并正确对齐
- 在 64 位边界上对齐C++结构数组?
- 使用 g++7 构建的代码在访问未对齐的内存时崩溃
- 在 capnp FlatArrayMessageReader 的对齐内存缓冲区中接收 zmq 消息
- 是否值得对齐变量?
- 初始化派生结构的基部分/意外打包派生结构字段以对齐基结构的间隙
- 对齐和对齐的实际用例C++关键字
- 如何减少代码的运行时间以对齐文本?
- 指向包含对齐 C 结构C++类的 C 指针的对齐问题
- Linux C++ 中的页面对齐内存分配
- C++ 类层次结构中的"对齐"是什么意思?
- 运行时错误:引用绑定到类型"int"的未对齐地址0xbebebebebebebec6,这需要 4 个字节对齐 (stl_vector.h)
- 具有调整对齐方式的类型定义
- C结构元素对齐(ansi)