我正在学习结构填充,并读到结构填充背后的原因是,如果结构的成员未对齐,处理器将无法在一个周期内读取/写入它们。通常,由 N
组成的数据类型的位置字节的地址应该是 N
的倍数.
假设这个结构例如:
struct X
{
char c;
// 3 bytes padding here so that i is aligned.
int i;
};
这里这个结构的大小应该是 8 个字节,c
默认是对齐的,因为它只占用1个字节,但是i
不是。对于 i
,我们需要在它之前添加 3 个字节的填充,以便它“对齐”并且只能在一个周期内访问。告诉我我是否遗漏了什么。1 - 对齐如何工作?成员与什么结盟?
2 - CPU 访问
N
有什么好处?位于 N
倍数的地址的字节数据类型?为什么例如,在上面的结构中,如果 i
位于地址 XXX3
(以 3 结尾,换句话说,不是 4 的倍数),为什么不从地址 XXX3
开始读取一个单词?为什么一定是4的倍数?大多数 CPU 访问的地址是否仅为字长的倍数?我相信 CPU 可以从任何字节开始从内存中读取一个单词。我错了吗?3 - 为什么编译器不对成员重新排序以尽可能多地占用空间?排序重要吗?我不确定是否有人使用实际的偏移量来访问成员。这意味着如果有一个结构
X x
,通常成员的访问方式如下:x.i
不是 *(&x + 4)
.在后一种情况下,排序实际上很重要,但在第一种情况下(我相信每个人都使用),排序应该无关紧要。我必须注意,在这个例子中,这无关紧要,因为如果 i
来到 c
此外,最后会有一个 3 字节的填充。我问一般为什么?4 - 我读到这不再重要了,CPU 现在通常可以访问非对齐成员,花费与对齐成员相同的时间。真的吗?如果是,那为什么?
最后,如果有好的地方可以学习更多,我将不胜感激。
最佳答案
_Alignof(type)
对齐.原则上允许实现进一步对齐,但这通常是不可取的,并且没有主要实现这样做。Alignment is a platform architecture constraint. Misaligned data access can be expensive (up to x16 as expensive in performance) as aligned access on some architectures, and can thwart atomic read/write (only relevant for multithreaded applications), or be unsupported entirely (causing a process fault). Other architectures can handle them without issue, and other architectures can handle them but at a performance penalty (so the compiler errs on the side of performance).
编写语言标准以允许此类平台约束。
Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.
memcpy
或 memmove
通过具有不同对齐方式的缓冲区),但这并没有改变以下事实:这些操作往往更昂贵,并且它们不适用于诸如原子操作之类的某些事情。关于c++ - 为什么编译器在 C/C++ 中填充结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63294333/