内存分配栈
Memory allocation stack
在栈中,内存是为main
预留的,我们称之为main
函数的栈帧。
当我们调用Add
函数时,内存被保留在栈顶。在Add
函数栈帧中,a
和b
是局部指针,c
是一个计算和的整数,然后我们return引用。 c
是 Add
函数的局部变量。
现在当 Add
函数执行完成时,堆栈中的内存 space 也被释放,所以当我们尝试使用指针 [=23] 访问 main
中的这个地址时=],我们试图访问的基本上是一个释放的space。编译器给出了警告,但为什么它仍然正确打印值 5?
答案可能是机器没有释放内存 space 因为它认为没有必要,因为没有更多的功能。但是如果我们写另一个函数 Hello
那么它肯定会在调用堆栈中为 Add
函数释放 space 但程序仍然打印
Yay 5
是否因为像在堆中一样,我们需要在释放后分配一个指向 null
的指针,否则我们仍然可以访问它?类似的东西在这里相关吗?
/* void Hello()
{
printf("Yay");
} */
int* Add(int *a,int *b)
{
int c=*a+*b;
return &c;
}
int main()
{
int a=1,b=4;
int *p=Add(&a,&b);
// Hello();
printf("\t%d",*p);
return 0;
}
TL;DR 回答,这是未定义的行为。您不能推理 上述执行的任何输出。如果它最终打印出您的手机 phone 号码或邮政编码,请不要感到惊讶。 :-)
作用域过期后,堆栈位置发生的变化取决于环境。如果不需要,分配给 c
的堆栈 space 可能不会被重用,因此您会看到 assumed proper 输出,但仍然 是未定义。总有一天,在不同的环境中,你可能会看到不同的答案。
Mr. Mothit Jain's 对此给出了非常详细的解释。
假设 c
是局部 int
变量,在函数调用后访问 c
是 undefined-behavior
并且可能会打印预期的结果,或者可能会做一些意想不到的事情。
虽然C
没有强制要求,但通常它是使用堆栈实现的。出于性能原因,当函数 returns 时,它保持堆栈区域不变。这就是您看到值 5
即 1+4
的原因。但你永远不应该指望这个。
当您使用第二个函数时,行为仍未定义,因此您可以获得任何输出。实际上,如果您在第二个函数中定义另一个变量并使用它,输出可能会改变。
+-----------------+
.(local variables).
|'''''''''''''''''|
| |
+----------------+ . PRINTF FUNCTION .
| c = 42 | | |
|''''''''''''''''| +-----------------+
| | | |
. ADD FUNCTION . . HELLO FUNCTION .
| | | |
+----------------+ +-----------------+
| b = 4 | | b = 4 |
|''''''''''''''''| |'''''''''''''''''|
| a = 1 | | a = 1 |
|''''''''''''''''| |'''''''''''''''''|
| | | |
. MAIN FUNCTION . . MAIN FUNCTION .
| | | |
+----------------+ +-----------------+
在上图中,我试图直观地表示当您在 Add
函数和 Hello
函数内部时堆栈可能的堆栈外观。您可以看到 Hello
没有弄乱在 Add
函数中为 c
保留的堆栈内存。
您可以通过将 Hello
函数重写为
来验证这一点
void Hello()
{
int i = 42;
printf("Yay - %d\n", i);
}
可以在main
中打印42
。
为了完全理解这一点,我建议您为您的处理器学习汇编,看看您的代码是如何编译的。在这一点上,我认为如果我说从函数返回不调用任何内存释放函数,它只是调整寄存器并且因为在添加和打印之间你没有做任何会改变 "deallocated" 上的值的事情,我认为会有帮助堆栈,你得到的数字。尝试调用一个 returns.. pfft 我不知道 77 之间的函数(但请将其保存到局部变量!),您将打印出不同的结果。学会汇编,做个合格的程序员
Hello
函数不会将任何新内容放入堆栈,因为它没有自动变量。因此之前被 c
占用的内存位置仍然没有改变。更改 Hello
以便它修改内存,您将更改 p
处的值。
void Hello(void)
{
//This will overwrite the memory previously containing '5' with '3`, the number
//of characters output by the printf() function.
int grub = printf("Yay");
}
我想是因为你没有在Hello函数中定义"stack variable",当我运行下面的程序时:
#include <stdio.h>
void Hello()
{
int tt = 100;
int tt1 = 5000;
printf("Yay");
}
int* Add(int *a,int *b)
{
int c=*a+*b;
return &c;
}
int main()
{
int a=1,b=4;
int *p=Add(&a,&b);
Hello();
printf("\t%d",*p);
return 0;
}
它在我的 Linux 中打印 5000 并且在我的 Mac 中打印 1,无论如何我认为它们是两者都出乎意料。
在栈中,内存是为main
预留的,我们称之为main
函数的栈帧。
当我们调用Add
函数时,内存被保留在栈顶。在Add
函数栈帧中,a
和b
是局部指针,c
是一个计算和的整数,然后我们return引用。 c
是 Add
函数的局部变量。
现在当 Add
函数执行完成时,堆栈中的内存 space 也被释放,所以当我们尝试使用指针 [=23] 访问 main
中的这个地址时=],我们试图访问的基本上是一个释放的space。编译器给出了警告,但为什么它仍然正确打印值 5?
答案可能是机器没有释放内存 space 因为它认为没有必要,因为没有更多的功能。但是如果我们写另一个函数 Hello
那么它肯定会在调用堆栈中为 Add
函数释放 space 但程序仍然打印
Yay 5
是否因为像在堆中一样,我们需要在释放后分配一个指向 null
的指针,否则我们仍然可以访问它?类似的东西在这里相关吗?
/* void Hello()
{
printf("Yay");
} */
int* Add(int *a,int *b)
{
int c=*a+*b;
return &c;
}
int main()
{
int a=1,b=4;
int *p=Add(&a,&b);
// Hello();
printf("\t%d",*p);
return 0;
}
TL;DR 回答,这是未定义的行为。您不能推理 上述执行的任何输出。如果它最终打印出您的手机 phone 号码或邮政编码,请不要感到惊讶。 :-)
作用域过期后,堆栈位置发生的变化取决于环境。如果不需要,分配给 c
的堆栈 space 可能不会被重用,因此您会看到 assumed proper 输出,但仍然 是未定义。总有一天,在不同的环境中,你可能会看到不同的答案。
Mr. Mothit Jain's
假设 c
是局部 int
变量,在函数调用后访问 c
是 undefined-behavior
并且可能会打印预期的结果,或者可能会做一些意想不到的事情。
虽然C
没有强制要求,但通常它是使用堆栈实现的。出于性能原因,当函数 returns 时,它保持堆栈区域不变。这就是您看到值 5
即 1+4
的原因。但你永远不应该指望这个。
当您使用第二个函数时,行为仍未定义,因此您可以获得任何输出。实际上,如果您在第二个函数中定义另一个变量并使用它,输出可能会改变。
+-----------------+
.(local variables).
|'''''''''''''''''|
| |
+----------------+ . PRINTF FUNCTION .
| c = 42 | | |
|''''''''''''''''| +-----------------+
| | | |
. ADD FUNCTION . . HELLO FUNCTION .
| | | |
+----------------+ +-----------------+
| b = 4 | | b = 4 |
|''''''''''''''''| |'''''''''''''''''|
| a = 1 | | a = 1 |
|''''''''''''''''| |'''''''''''''''''|
| | | |
. MAIN FUNCTION . . MAIN FUNCTION .
| | | |
+----------------+ +-----------------+
在上图中,我试图直观地表示当您在 Add
函数和 Hello
函数内部时堆栈可能的堆栈外观。您可以看到 Hello
没有弄乱在 Add
函数中为 c
保留的堆栈内存。
您可以通过将 Hello
函数重写为
void Hello()
{
int i = 42;
printf("Yay - %d\n", i);
}
可以在main
中打印42
。
为了完全理解这一点,我建议您为您的处理器学习汇编,看看您的代码是如何编译的。在这一点上,我认为如果我说从函数返回不调用任何内存释放函数,它只是调整寄存器并且因为在添加和打印之间你没有做任何会改变 "deallocated" 上的值的事情,我认为会有帮助堆栈,你得到的数字。尝试调用一个 returns.. pfft 我不知道 77 之间的函数(但请将其保存到局部变量!),您将打印出不同的结果。学会汇编,做个合格的程序员
Hello
函数不会将任何新内容放入堆栈,因为它没有自动变量。因此之前被 c
占用的内存位置仍然没有改变。更改 Hello
以便它修改内存,您将更改 p
处的值。
void Hello(void)
{
//This will overwrite the memory previously containing '5' with '3`, the number
//of characters output by the printf() function.
int grub = printf("Yay");
}
我想是因为你没有在Hello函数中定义"stack variable",当我运行下面的程序时:
#include <stdio.h>
void Hello()
{
int tt = 100;
int tt1 = 5000;
printf("Yay");
}
int* Add(int *a,int *b)
{
int c=*a+*b;
return &c;
}
int main()
{
int a=1,b=4;
int *p=Add(&a,&b);
Hello();
printf("\t%d",*p);
return 0;
}
它在我的 Linux 中打印 5000 并且在我的 Mac 中打印 1,无论如何我认为它们是两者都出乎意料。