C 堆栈中的变量&;堆

C 堆栈中的变量&;堆,c,stack,heap-memory,C,Stack,Heap Memory,在本文所写内容的上下文中 理解堆栈的一个关键是当函数 退出时,其所有变量都从堆栈中弹出(因此 永远失去)。因此,堆栈变量本质上是局部的 因此,堆栈中属于该函数的所有变量都会弹出,除了可能返回给该函数的值(或者可能为父函数重新分配?),或者如果它不是静态的 但是这个特殊的程序运行得非常好 #include<stdio.h> int* func() { int a=6; int *b; b=&a; printf("in func - %d \n",*b); return b

在本文所写内容的上下文中

理解堆栈的一个关键是当函数 退出时,其所有变量都从堆栈中弹出(因此 永远失去)。因此,堆栈变量本质上是局部的

因此,堆栈中属于该函数的所有变量都会弹出,除了可能返回给该函数的值(或者可能为父函数重新分配?),或者如果它不是静态的

但是这个特殊的程序运行得非常好

#include<stdio.h>

int* func()
{
int a=6;
int *b;
b=&a;
printf("in func - %d \n",*b);

return b;
}

void func2()
{
    int a,c;
    a=99;
    c=2*a;
    printf("in func 2 - %d \n",c);
}

void main()
{
int *b;
b=func();
func2();
printf("in main - %d",*b);
}
我认为用户分配的变量(使用calloc、malloc、realloc)可以被其他函数访问,因为它们在堆中,正如文章所说。
但是,如果我们创建一个指向堆栈中的局部变量的指针,并返回该指针,那么该变量也可以在其他函数中访问。

您返回的是地址,它看起来是正确的,因为没有出现任何东西来替换该位置的内存内容。但情况并非如此。如果在func和printf之间调用函数,那么通过返回局部变量的地址(并尝试在调用者中取消引用),您的程序可能会调用未定义的行为,从而得到不同的结果。未定义行为的一个可能结果是您的程序似乎工作正常。但是,如果在调用
func
printf
之间更改代码以调用另一个函数(尤其是创建和设置局部变量的函数),则可能会得到不同的结果

显然,用来占用的
a
内存单元1仍然存在,并将包含
a
的最后一个值,直到有其他内容覆盖它。你只是碰巧在其他东西到达之前访问了那个存储单元



1.我们这里说的是虚拟内存,不是物理内存。

永远不要。曾经说。“完全正常”。尝试在调用
func
printf
之间调用另一个函数。我最喜欢的一个函数是:当某个函数从堆栈中弹出时,它不会被删除!但是,堆栈被释放,因此可以(并且将)在这些局部变量所在的位置写入其他内容。因此,您的示例是有效的,因为您在调用
func
之后没有调用任何其他函数,但这并不意味着这是可以保证的,因为它似乎不起作用。我应该试试更大的功能吗?结果已作为编辑发布。似乎不起作用。我应该试试更大的功能吗?结果已作为编辑发布。@ShauryaChaudhuri抱歉,我回来晚了,但所有重要的评论都在另一个答案中给出:)似乎不起作用。我应该试试更大的功能吗?结果已作为编辑发布。@John Bode不清楚为什么会出现“记忆”脚注。即使使用物理内存,
a
使用的内存单元仍然存在,并且将包含
a
的最后一个值,直到其他内容覆盖它(或电源循环)。@ShauryaChaudhuri:原因可能有很多;再次强调,这一点是
func
的行为是未定义的,几乎任何结果(包括看起来正常工作)都是可能的。您不应该依赖于这种行为是可重复或可预测的。返回
auto
变量的地址并试图在该变量的生存期之外取消对其的引用是一个编码错误,到此为止。@chux:只是试图强调一个独立于任何物理体系结构的抽象内存模型。显然,在一个没有虚拟内存的系统上,我们谈论的是一个物理内存单元。似乎足够有效。因此,在函数调用权限之后,内存可能会被编辑,也可能不会被编辑。这是完全不可预测的。也许有一次它会像预期的那样给出o/p,而另一次它可能会覆盖以前的堆栈内存空间,并给出一个完全不同的o/p。我的理解正确吗?
C:\Users\Shaurya\Desktop>gcc asw.c

C:\Users\Shaurya\Desktop>a
in func - 6
in func 2 - 198
in main - 6
C:\Users\Shaurya\Desktop>