【问题标题】:Does the stack grow continuously?堆栈是否持续增长?
【发布时间】:2016-12-21 04:39:59
【问题描述】:

我想知道为什么这段代码没有按预期工作。

typedef char uint8;

  int main(int argc, const char * argv[]) {
  // insert code here...

  uint8 number_1 = 3;
  uint8 number_2 = 1;
  uint8 *PointerToNumber = &number_1;

  printf("%d \n", *PointerToNumber);
  ++PointerToNumber;
  printf("%d \n", *PointerToNumber);

  return 0;
}

这个程序打印 3 和 -112。但是,如果堆栈连续增长,它不应该打印 3 和 1 吗?

所以,如果我指向 number_1,然后增加 uint8 类型的指针地址,它不应该指向 number_2,因为它是在 number_2 之后声明的吗?

【问题讨论】:

  • 这不是堆栈增长方式的问题,而是编译器选择如何排列局部变量的问题。
  • 两个变量之间可能有未使用的字节......并且不能保证变量被放置在任何特定的位置或顺序,甚至根本不被包含(它们可以根据具体情况进行优化)它们是如何使用的)。
  • 你不能依赖局部变量在内存中的位置,但number_2可能在number_1之后的下一个低地址。
  • C 语言中没有栈。您的代码调用了未定义的行为。
  • C语言定义中没有提到栈。这是一个实现细节。

标签: c memory stack


【解决方案1】:
++PointerToNumber;
printf("%d \n", *PointerToNumber);

是未定义行为的原因。试图为任何行为辩护是没有意义的。程序的行为可能会随着优化级别的变化、不同的编译器选项和不同的编译器而改变。

在这种情况下,优化器可以选择不为 number_2 分配任何空间,因为它没有在函数中使用。

【讨论】:

    【解决方案2】:

    好吧,正如有人评论的那样,number-2 可能在 number_1 之后的下一个较低地址。 因此,--PointerToNumber 不是执行 ++PointerToNumber,而是创建预期结果(打印“1”)。

    【讨论】:

    • 再一次,不保证。尝试使用优化进行编译,看看它是否仍然有效。此外,在优化关闭的情况下,我得到了您对原始代码所期望的结果,仅仅是因为我的编译器对变量的排序与您的不同......并且在优化后,两者都不起作用。
    • 是的,我知道这一点。我只是想验证堆栈作为 LIFO 内存的整体概念。
    • 局部变量的放置与栈是LIFO无关。调用函数时通常发生的情况是调用者将参数和返回地址压入堆栈并调用该函数。然后被调用的函数将帧指针设置为堆栈指针的值。然后堆栈指针会按函数本地存储所需的空间量递减。局部变量被分配在该空间中的位置(表示为从帧指针的负偏移量),但它们可以在其中的任何位置。这完全取决于编译器。
    猜你喜欢
    • 2012-10-08
    • 2021-12-08
    • 2011-03-23
    • 2011-04-04
    • 1970-01-01
    • 2011-12-28
    • 1970-01-01
    • 2020-07-20
    • 1970-01-01
    相关资源
    最近更新 更多