考虑以下代码段(在32位Intel / Linux系统上):
struct mystruct { char a; int b; short c; char d; }; int main() { struct mystruct foo[3]; char ch; int i; printf("%p %p %p %p %p\n", &foo[0], &foo[1], &foo[2], &ch, &i); return 0; }
以下哪一项最有可能成为其产出的候选人?
0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeece8f 0xfeeece88
0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeeceb4 0xfeeeceb8
0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeeceb4 0xfeeeceb5
- 醇>
0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeece8c 0xfeeece88
输出是选项(1)。我无法理解,选项a如何是正确的答案..
堆栈从较高地址增长到较低地址。此处foo[3]
,foo[2]
,foo[1]
,foo[0]
,ch
,i
... i
位于较低地址堆栈和foo[3]
在更高的地址。此处sizeof(mystruct)
为16,因此foo[3]
,foo[2]
,foo[1]
,ch
的地址间隔为16。
我无法通过以下地址获取地址差异16:
0xfeeece90 0xfeeece9c 0xfeeecea8 0xfeeece8f 0xfeeece88
答案 0 :(得分:4)
给你的选项假设一个12个字节的sizeof(mystruct)
,这是合理的,因为你有
a
位于偏移0 b
与4个字节对齐b
抵消4 c
偏移8(不需要填充,我们已经是2的倍数)d
偏移量为10(无需填充,char
不需要任何特定对齐)b
保持与4个字节边界对齐)。因此,在这方面所有选择都是合理的;接下来是ch
;假设编译器保持变量的顺序(在优化的构建中肯定不合理)将位于foo
之上。 foo
从0xfeeece90
开始,ch
没有对齐要求,因此它将是0xfeeece8f
。最后,i
将位于ch
上方最近的4字节边界,这确实是0xfeeece88
。
再次说明:这个讨论对于{em>与struct
有关是现实的,在讨论当地人时并不是这样。在优化的构建中,声明的顺序无关紧要,编译器可能会对它们进行重新排序以避免浪费空间(并且,如果您不要求它们的地址,则会尝试将它们放入寄存器中)。