char与char数组的堆栈变量分配:为什么会有区别?

时间:2016-08-28 20:20:36

标签: c gcc

这个简单的程序打印出两个变量的地址:

int main (int argc, char **argv)
{
   float My_Float = 10.5;
   char  c;

   printf("addr of My_float is %p\naddr of        c is %p\n", &My_Float, &c);
}

输出,如预期:

addr of My_float is 0x7fff52a7eafc
addr of        c is 0x7fff52a7eafb

但是,这个(只有char数组而不是char的区别)有一个不同的地址,用于" c"。

int main (int argc, char **argv)
{
   float My_Float = 10.5;
   char  c[20];

   printf("addr of My_float is %p\naddr of        c is %p\n", &My_Float, &c);
}

addr of My_float is 0x7fff5b922adc
addr of        c is 0x7fff5b922af0

为什么' c'现在分配到不同的位置?更有趣的是,为什么会这样做?' c'在' My_Float'之后分配,考虑到堆栈向下增长 - 我预期' c'总是要有一个地址少于' My_Float'与第一个项目的情况一样。

我在使用x86处理器的Mac上运行GCC。

2 个答案:

答案 0 :(得分:1)

正如Sourav Ghosh所述,编译器可以自由地重新排序不在结构中的变量。出现这种情况有很多原因:

  • 内存对齐限制。从最受限制到最少受限制的变量排序减少了内存中的浪费。大多数数据类型仅限于可以从哪些地址开始。示例:chars可以是任何内容,短整数的地址(int16)通常必须是偶数。 int32的地址通常必须被4整除。指针往往属于最受限制的类别,在char cchar *ptr之间存在很大差异。
  • 如果程序存在错误,编译器可能会命令减少常见问题。 Hans Passant解决了这个问题。 UB是未定义的行为。
  • 神秘:通常与硬件行为或编译器编写者的优化或怪癖有关。

答案 1 :(得分:0)

对于任何变量,内存分配可以是向上堆叠向下增长堆栈。这取决于架构。但是数组的内存分配总是在增长堆栈