如何解决“ C”语言功能的特殊性
由于我是C语言的新手,所以我在functions
中遇到了一个奇特之处,因此向tutorials point学习它,这使我在理解它的同时还不知所措。
我了解到,如果在function
内定义了变量,则该函数是局部的scope
,并且每当控件从函数转移时,变量就不再可用和清除。
但是在我创建的情况下不是,下面的程序仍在打印变量p
的值,该变量在test
函数中定义,因此当从test
函数进行控制时为什么我仍然可以转移其价值?为什么仍在屏幕上打印变量p的值为80
?
#include <stdio.h>
int *test();
int main()
{
int *ab
ab = test();
printf("%d\n",*ab);
return 0;
}
int *test()
{
int p = 80;
return (&p);
}
请帮助我理解这种特殊性。
解决方法
您遇到的是undefined behavior的症状。
变量的生存期结束后,其地址不再有效。尝试取消引用该地址时,您可能会看到以前的值,或者可能看到其他内容。
尝试在printf
中复制main
调用,您可能会看到不同的值。
最有可能发生的情况是,在第一次调用printf
之前,包含p
的内存区域尚未被覆盖。然后,当实际调用printf
时,该函数的堆栈帧正在使用与test
的堆栈帧相同的内存,而p
先前使用的内存现在将被覆盖。因此,调用ab
后在main
中取消引用printf
时,您会看到该函数放置在其中的任何值。
访问范围外的变量是Undefined Behaviour,因此,根据定义,随着变量的变化(编译器标志,操作系统等),结果可能会无限且不可预测地变化
您的变量不会超出范围,但这仅表示已不再“保留”。但是,与较新的语言可能会引起编译时错误的语言不同,在C语言中,这只是一个警告,如果您具体要求编译器向您提供额外警告,则可能会出现
因此代码将编译。
此处,变量超出范围,但是,据推测,不会再使用任何内存,因此test的 address处的值保持不变。如果声明/初始化/使用了更多变量,则该地址很可能会被另一个值覆盖,并且您可能会打印出一些意外的东西,这是真实的,即使结果是意外的,因此您的问题是!
要记住的是-C中的变量就像大厅中的椅子(类似于内存)。椅子的位置,椅子的数量都是固定的/固定的。可以更改的是谁坐在椅子上。
因此,如果您让一个朋友坐在方便的椅子上,并在5分钟后告诉他不再需要他,那么他是否会呆在那里还是起床并有人代替他是您不敢预测的事情并且在范围外的地址进行读取同样是不确定的,因为无法事先预测!
其他类比可能是停车位,集装箱等。
区别在于地址不会会被覆盖/“删除”,直到出现需要存储的其他内容(这也是磁盘管理“删除”的方式,实际上这不过是什么而已) 取消保留硬件位置)。
考虑到这一点,从效率的角度来看,这很有道理-您不再需要浪费时间进行无用的“用0覆盖”或其他操作,而只需 您具有存储到内存中的真实价值!
(1个操作而不是2个工作的一半。)
,即使该变量不再应该“存在”,但计算机还是有点懒惰,并且不会删除地址中的值。
这就是您可以操纵内存的方式,如果您尝试查看不属于程序的内存,您将能够看到一些奇怪的值,因为即使它们不属于程序,它们也会保留在内存中不再使用了。
,以下是一个示例,可以说明您正在查看的UB:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int *test();
void run_random();
int main()
{
srand(time(NULL));
int *ab;
int i=0,N = 5;
for (i=0; i<N; ++i){
ab = test();
run_random();
printf("%d\n",*ab);
}
return 0;
}
int *test()
{
int p = 80;
return (&p);
}
void run_random()
{
int i=0,N=1000;
for (i=0; i<N; ++i){
int rvar = rand();
}
}
在您的代码中,test()
中的变量恰好在堆栈存储器上仍具有预期值。这是我在循环中重新运行该功能时看到的-*ab
仍等于80,如果注释掉run_random()
调用,您也可以看到它。
但是当我添加第二个呼叫时,对run_random()
的呼叫-我开始在ab
中得到等于{{1}的N
的{{1}},即1000,因为该内存位置是现在填充了另一个变量的值(run_random()
停止执行后,操作系统便可以免费使用它作为开始。)
在您的情况下,您可能最终还会看到其他内容,甚至可能仍然是预期值。那就是UB的意义,您真的不知道会弹出什么。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。