`__attribute((packed))`是否影响其他数据结构的对齐?

hgc7kmma  于 10个月前  发布在  其他
关注(0)|答案(2)|浏览(104)

我试图理解为什么在处理数据结构时对齐很重要,为什么它会影响内存访问性能。我偶然发现了一个C语法,__attribute__((packed));,据我所知,它指示编译器不要为对齐填充额外的位。
请说:

struct sampleStruct{
    uint8_t foo;
    uint8_t anotherFoo;
};

字符串
fooanotherFoo等于16位,但增加了额外的16位以与32位处理器的自然字大小对齐。
让我们添加另一个数据结构:

struct anotherStruct{
    uint8_t fooZero;
    uint8_t fooOne;
}__attribute__((packed));

struct sampleStruct{
    uint8_t foo;
    uint8_t anotherFoo;
};


我的问题是,当初始化一个打包的数据结构时,它会影响其他数据结构在内存中的对齐方式吗?

  • 也许编译器重新排序了这些数据结构的创建方式?(sampleStruct然后anotherStruct)
  • 如果有两个程序运行在一个系统上,第一个程序的struct未对齐,而第二个程序的struct对齐,会在内存中留下“间隙”吗?

很抱歉这个愚蠢的问题。这个问题已经困扰我很长一段时间了。我想知道内存对齐是如何工作的,以及它如何影响处理器访问内存。

epfja78i

epfja78i1#

一般来说,如果一个变量位于一个可以被 n 整除的地址,那么它可以更有效地从内存中读取/写入。在某些处理器上(特别是,不是x86),尝试以非对齐的方式读取/写入可能会导致硬件陷阱。
因此,虽然打包一个结构可以减少它的大小,但这通常意味着更慢的内存访问(如果访问可以发生的话)。
打包结构一般不会影响其他结构或其他类型。每个不同的类型,无论是“基”类型还是派生类型,都有自己的对齐方式,因此给定类型的变量将根据该类型的对齐方式以及可能存在的可用空间放置。其他类型的变量的对齐方式不会对其产生直接影响。
至于其他进程,它们是完全相互独立的,所以没有理由一个进程的内部数据结构会对另一个进程的内部数据结构产生任何影响。

fgw7neuy

fgw7neuy2#

你似乎不明白什么是对齐,什么是打包。
对齐仅仅意味着对象必须被发现/放置在一个可以被某个数字整除的地址上。一个类型的对齐与这个或其他程序或进程中其他类型的对齐没有关系,除非一个类型(数组,联合,结构)包含一个对象或另一个类型。
不正确的对齐可能会导致性能下降(或更糟)。
因为你的结构不受packed的影响,因为它不使用任何填充,所以让我们考虑一个不同的结构。

struct yetAnotherStruct {
    uint8_t  foo1;
    uint32_t foo2;
    uint8_t  foo3;
};

字符串
如果没有__attribute__((packed)),这可能会编译为:

  • 结构体的大小为12。
  • foo1是在偏移量0处找到的uint8_t
  • foo2是在偏移量4处找到的uint32_t
  • foo3是在偏移量8处找到的uint8_t
  • 必须放在一个能被4整除的地址。
+---+---+---+---+---+---+---+---+---+---+---+---+
| 1 | padding   | 2             | 3 | padding   |
+---+---+---+---+---+---+---+---+---+---+---+---+


使用__attribute__((packed)),编译为:

  • 结构体的大小为6。
  • foo1是在偏移量0处找到的uint8_t
  • foo2是在偏移量1处找到的uint32_t
  • foo3是在偏移量5处找到的uint8_t
  • 必须放在一个能被1整除的地址。
+---+---+---+---+---+---+
| 1 | 2             | 3 |
+---+---+---+---+---+---+


这些数字是它所改变的全部。使用这种类型的结构的代码使用这些数字来生成适当的CPU指令来访问,修改或分配结构。但仅此而已。
它不会影响此进程或其他进程中的任何其他结构(除非这些结构包含此结构)。

相关问题