我做了一个小测试,看看堆栈是如何在C应用程序中使用的。
#include <stdio.h>
void a(void)
{
int a = 0;
}
void b(void)
{
int b;
printf("%i\n", b++);
}
int main(void)
{
a();
b();
b();
b();
fflush(stdin), getc(stdin);
return 0;
}
在b
所在的堆栈中,a
是否分配在同一位置?我希望输出为0 1 2
,但我得到相同的垃圾值三次。那是为什么?
答案 0 :(得分:10)
关于获得关于为什么获得所得内容的明确答案的唯一方法是从编译器获取汇编语言输出并查看它正在做什么。猜测,a()
的整体被删除为死代码,b
可能正在寄存器中分配,所以即使a
已被分配和初始化,也有仍然是b
不会在同一存储中结束的公平机会。
从语言的角度来看,实际上没有任何答案 - 您的代码只是使用未初始化的变量而具有未定义的行为。只是为了增加对伤害的侮辱,你的fflush(stdin)
也会导致未定义的行为,所以即使代码的其余部分有意义,你仍然无法保证它会产生什么输出。
答案 1 :(得分:3)
您正在做的是调用未定义的行为,但在C99中,值为 indeterminate 。无论哪种方式,你都不知道到底会发生什么。
离开方法时,无法保证堆栈的状态,也没有未初始化变量的值。
答案 2 :(得分:3)
我可能猜测你输出了所有的零,但不一定是这种情况。在函数b中,您声明了为每次执行代码创建的新int b。 B在您的代码中未初始化,但某些编译器会将此值归零。这不是标准的,不应指望。您应该始终初始化变量。
就堆栈而言,这是特定于实现的,并且取决于编译器,优化器设置等。无法保证此变量永远存在于堆栈中。有可能它没有,鉴于范围的持续时间很短,它可能只存在于CPU寄存器中。
在上面的代码中,b和a是完全独立的变量,因此不应指望它们具有相同的值,即使它们存储在同一个内存位置。
答案 3 :(得分:2)
作为函数b++
中b()
的一部分的分配不一定由编译器执行,因为之后不会读取b
。但更重要的是,如果你没有初始化器:
The initial value of the object is indeterminate.
就是这样。 (而不是UB,正如其他人所说。)编译器可以自由地以任何方式实现它。
NB:“标准”一词不会出现在C标准中的任何位置。虽然这是在C中实现auto
变量的一个方便概念,但编译器没有义务将该概念用于给定变量,特别是没有义务将变量存储在内存中。如果平台允许,它可以将所有变量保存在寄存器中。因此,如果您查看为a()
生成的汇编程序,您很可能只看到 nothing ,只是一个空的返回。
答案 4 :(得分:1)
您是否已阅读这些幻灯片?
http://www.slideshare.net/olvemaudal/deep-c
有关于此类堆栈行为的讨论。当然,你永远不能依赖于自动变量中的值。编译器可以自由地将这些变量放在寄存器上。或者在堆栈上。
答案 5 :(得分:1)
B的值是不确定。您无法通过运行此程序来学习任何内容。