2

对于某些结构splab

int main() {

   int a;
   struct splab *s1;
   int b;

   printf("%x\n",&a);
   printf("%x\n",&b);

   return 0;
 }

我想我应该进入第二个打印:(bfc251e8 - 8即占 的空间s1)。

相反,我得到了:

bfc251e8
bfc251ec

为什么?

4

3 回答 3

5

这不仅仅是关于变量的顺序。您从不使用s1,编译器可以(并且可能)简单地优化它而不在堆栈上分配空间。

a如果我尝试只打印and的地址,这就是我得到的结果b,就像你做的那样:

ffeb7448 (&a)
ffeb7444 (&b)

即4个字节的差异。

s1如果我尝试打印也的地址(因此最终使用声明) ,这是我得到的s1

ffe109cc (&a)
ffe109c8 (&s1)
ffe109c4 (&b)

您可以看到它实际上确实位于ab这一次之间(并不总是,正如其他答案已经指出的那样),并且ab8 个字节而不是 4 个字节分隔。


另一个稍微相关的点与对齐有关:

例如:

struct foo
{
  int a;
  char b;
};

虽然这个结构在具有 4 字节整数的机器上看起来可能是 5 字节宽,但我的编译器说,sizeof (struct foo) == 8.

这样foo总是在 8 字节边界对齐(这包括使用struct foo局部变量)。

例如

int bar (void)
{
  struct foo a;
  struct foo b;

  /* Do some work.  */
}

在这里,a并且b在我的机器编译器上被 8 个字节分隔,即使每个foo实际上只使用 5 个字节。

所有这一切都表明:在编写代码时,永远不要假设与宽度、对齐、相对位置等有关的任何事情。

于 2012-07-02T11:49:28.260 回答
2

编译器可以自由地重新排序变量在堆栈上的位置,因此变量可能位于指针b之前s1,尽管后者是在中间声明的。

由于某些数据类型需要对齐,因此此类重新排列可能会提高内存利用率,从而消除任何可能的间隙。

于 2012-07-02T11:35:01.893 回答
1

你是说因为指针s1被分配在ab需要的地址之间根据指针使用内存的数量而变化?(我不太清楚)。

如果是这样,我认为您不能指望这一点,如何在不同变量之间分配内存不在您的控制之下。看起来内存是以线性方式分配的,但这不是您可以依赖的。

如果我对您的问题的解释有误/您能否重新措辞/澄清一下?

于 2012-07-02T11:31:22.020 回答