这是一个面试问题 . 直到现在,我曾经认为这些问题纯粹依赖于编译器,不应该担心我,但现在,我对它很好奇 .
假设您有两种结构:
struct A {
int* a;
char b;
}
而且,
struct B {
char a;
int* b;
}
那么你更喜欢哪一个?为什么?我的回答是这样的(虽然我有点在黑暗中拍摄)第一个结构应该是首选的,因为编译器为字大小的一些倍数(这是指针的大小 - 在32上的4个字节)分配结构的空间位机和64位的8字节) . 因此,对于这两种结构,编译器将分配8个字节(假设它是32位机器) . 但是,在第一种情况下,填充将在我的所有变量之后完成(即在a和b之后) . 因此,即使有一些机会,b得到一些溢出的值并破坏我的下一个填充字节,但我的a仍然是安全的 .
他似乎并不高兴,并要求第一个结构在第二个结构上的一个缺点 . 我没有太多话要说 . :d
请帮我解答 .
5 回答
我不认为任何这种结构都有优势 . 这个等式中有一个(!)常数 . 结构成员的顺序保证是声明的 .
所以如下所示,第二个结构 might 有一个优势,因为它可能有一个较小的尺寸,但不是在你的例子中,因为它们可能具有相同的大小:
比 .
A little more explanation regarding comments below:
以下所有不是100%,但结构将在32位系统中构造的常见方式,其中int为32位:
结构X:
结构Y:
有些机器access data more efficiently当值与某些边界对齐时 . 一些require数据要对齐 .
所以你可以拥有
我个人认为第一个结构与第二个结构相比并不缺点 .
在这种特殊情况下,我无法想到第一个结构在第二个结构上的缺点,但是有可能提出一些例子,其中将最大成员放在第一位的一般规则存在缺点:
我还听说过大型结构的相当复杂的情况,其中CPU具有用于访问指针偏移的快速寻址模式,用于较小的偏移值(例如,高达8位,或立即值的某些其他限制) . 您最好通过在最快的指令范围内放置尽可能多的最常用字段来对大型结构进行微观优化 .
CPU甚至可能具有指针偏移和指针4 *偏移的快速寻址 . 然后假设您有64个char字段和64个int字段:如果先放置char字段,那么可以使用最佳指令来处理这两种类型的所有字段,而如果先将int字段放入,则将不是4的字段放入-aligned只需要以不同方式访问,可能是通过将常量加载到寄存器而不是立即值,因为它们超出了256字节的限制 .
从来没有必须自己做,例如x86无论如何都允许大的直接值 . 除非他们花费大量时间盯着装配,否则这不是任何人通常会想到的那种优化 .
简而言之,在一般情况下选择任何一个都没有优势 . 选择在实践中最重要的唯一情况是,如果启用了结构打包,则
struct A
将是更好的选择(因为两个字段将在内存中对齐,而在struct B
中b
字段将位于奇数偏移处) . 结构打包意味着在结构内部不插入填充字节 .但是,这是一种相当罕见的情况:结构打包通常仅在特定情况下启用 . 这不是大多数计划的关注点 . 并且它也不能通过C标准中的任何便携式结构来控制 .
这是也有一些猜测,但大多数编译器都有一个未对齐选项,明确不会添加填充字节 . 然后,这需要(在某些平台上)运行时修复(硬件陷阱)来动态地对齐访问(具有相应的性能损失) . 如果我记得正确HPUX属于这一类 . 因此,即使使用了错位编译器选项,第一个结构字段仍然是对齐的(因为正如您所说的填充将在最后) .