关于C局部变量的生命周期。

KimboQi 2012-06-06 02:16:28
写了两个函数:
struct TestNode* test_node1 (TestList *l) {
TestNode tn;
tn.n = 12;
printf("%p\n", &tn);
*l = &tn;
return &tn;
}
struct TestNode* test_node2 (TestList *l) {
TestNode *tn = (TestNode *) malloc (sizeof(struct TestNode));
tn -> n = 12;
printf("%p\n", &tn);
*l = tn;
return tn;
}
第一个函数 程序编译的时候警告,不能返回局部变量的地址,而第二种方式确不发出警告,函数的局部变量不是放在栈中吗?当函数调用结束的时候不是栈空间会北回收吗,那么局部变量的地址被外部变量所引用的时候,那么这快栈中的数据会变无效吗?之类就想不通啊
...全文
2050 49 打赏 收藏 转发到动态 举报
写回复
用AI写文章
49 条回复
切换为时间正序
请发表友善的回复…
发表回复
新光 2013-04-07
  • 打赏
  • 举报
回复
函数到'}'的时候函数生命周期结束,局部常用变量被回收,这样你返回的变量地址是没有意义的,因为你如果在其他函数调用这个函数的时候,这个函数返回的地址已经被回收了
新光 2013-04-07
  • 打赏
  • 举报
回复
函数到'}'的时候函数生命周期结束,局部常用变量被回收,这样你返回的变量地址是没有意义的,因为你如果在其他函数调用这个函数的时候,这个函数返回的地址已经被回收了
mamamiya 2012-06-16
  • 打赏
  • 举报
回复
为什么赵老师每次都用同样的内容回复别人。。虽然我很赞同赵老师的回复。但是您别每次都这样啊。。
wintree 2012-06-15
  • 打赏
  • 举报
回复
我就一句话 不要返回局部变量。。。。
battleining 2012-06-14
  • 打赏
  • 举报
回复
同看赵老师
xuxijie8 2012-06-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]
函数返回了,局部变量地址就没有意义了,理论上这快地址还没被擦写。
但编译器和CPU都不保证这快地址的有效性拉
[/Quote]+1
xuxijie8 2012-06-14
  • 打赏
  • 举报
回复
我是来看赵老师的
xuxijie8 2012-06-14
  • 打赏
  • 举报
回复
10楼正解
scgywx 2012-06-14
  • 打赏
  • 举报
回复
[Quote=引用 30 楼 的回复:]

struct TestNode* test_node1 (TestList *l) {
TestNode tn;
tn.n = 12;
printf("%p\n", &tn);
*l = &tn;
return &tn;
}
struct TestNode* test_node2 (TestList *l) {
TestNode *……
[/Quote]

第二个是返回struct TestNode*,你要再加个&, 那就是返回一个struct TestNode**了,,跟函数返回值不一致,不应该是警告,而应该是错误。
疯疯癫癫 2012-06-14
  • 打赏
  • 举报
回复
+1 同意
[Quote=引用 14 楼 的回复:]
函数返回了,局部变量地址就没有意义了,理论上这快地址还没被擦写。
但编译器和CPU都不保证这快地址的有效性拉
[/Quote]
UnknowName 2012-06-14
  • 打赏
  • 举报
回复
不让你引用局部变量的地址是因为,局部变量在函数返回就被释放了。简单的说,原来局部变量所占用的空间会被其他的变量或者值覆盖掉。这点相信你已经明白了。
你不明白的是,返回一个变量的引用和返回一个指向malloc分配的内存的区别。

简单的说:你返回的局部变量的引用,变量的值分配在栈中,函数返回栈要被释放。
你返回的malloc分配的变量,变量的值分配的堆中,函数返回堆中的内存并没有被释放。
并且如果你不调用free(), 堆中的分配的那块内存知道程序结束也不会释放。

还有重要的一点,你会指向堆内存的指针,局部变量的值会被复制一份返回。
所以当 TestNode* tn = test_node2(); 返回给tn的值不过是局部变量的一个复制。
FrankHB1989 2012-06-12
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 的回复:]

感谢各位的回答,对个位的回答和我的一些理解做个总结,各位顺便请看看总结的对不对:
1. c语言函数的动态分配的变量拥有的生命周期只限于函数调用期间,因为函数调用时期,所有的动态局部变量都存放在系统的栈帧中。当函数调用结束时,此栈帧就会被系统回收,(回收的概念是指,这块存储空间可以被其他程序访问了,而不是清除这块内存空间的数据,有时碰到函数局部变量值后仍然存在,就是因为这块栈空间还的数据还没有被……
[/Quote]
有点问题。
1.lifetime和storage duration是两个概念。不像C++,C对storage duration只视为分类,只说有几个而不是几种(因为本身就是种类):static, thread, automatic, allocated。所以说对象具有的storage duration不管对象在哪个函数中声明。而automatic对象的lifetime并不对应函数或函数作用域(函数作用域只适用于label而不是对象;作用域在C中其实也只是“几个”,特殊地,任意结束为止相同的作用域被视为等价),而是对应块作用域(当一个块是函数体的时候基本同LZ的理解)。
2.非static/_Thread_local修饰的automatic storage duration对象的确可以算“动态”——在运行时分配的,但分配多少还是静态确定的。而malloc得到的allocated storage duration对象反而是更正牌的“动态”。

wapjia43106140 2012-06-12
  • 打赏
  • 举报
回复
你没明白指针与变量的区别。多实践看书吧。
nvrbnthr 2012-06-11
  • 打赏
  • 举报
回复
所以只是警告而已!又没有报错!

yujie_v 2012-06-11
  • 打赏
  • 举报
回复
结果不确定而已
wizard_tiger 2012-06-09
  • 打赏
  • 举报
回复
函数结束后局部变量的地址只是被回收了,也就是说可以被其它程序使用,
但在没有被使用前值还是没有变化过的。
胡小来 2012-06-09
  • 打赏
  • 举报
回复
多么人性化的警告………… 你认为这警告多余的?
ccnyou 2012-06-07
  • 打赏
  • 举报
回复
struct TestNode* test_node1 (TestList *l) {
TestNode tn;
tn.n = 12;
printf("%p\n", &tn);
*l = &tn;
return &tn;
}
struct TestNode* test_node2 (TestList *l) {
TestNode *tn = (TestNode *) malloc (sizeof(struct TestNode));
tn -> n = 12;
printf("%p\n", &tn);
*l = tn;
return tn;
}

你把第二个加上 & 也警告了
yangkai7758 2012-06-07
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

问题的重点不是在这里,问题是为什么返回局部变量的地址会被警告,而实际上确实能得到局部变量的地址的啊?
引用 3 楼 的回复:

malloc的东西在堆里面....骚年多看书
[/Quote]
第一个返回的是局部变量的地址,局部变量分配在栈上,函数结束后就被释放了,返回它的地址当然不对
第二个返回的是局部变量的,这个局部变量指向的是堆中分配的空间,也就是值等于堆中空间的首地址
本质上,你两个函数返回的东西都不一样……
KimboQi 2012-06-07
  • 打赏
  • 举报
回复
我觉得这比喻就不对了吧。c语言定义变量生命周期的时候,就是在块结束之后或者函数结束之后就结束了的。生命结束了 只是尸体没销毁罢了。而是暂存在内存中罢了,系统要用空间的时候自然会销毁掉的。科学就是严谨的,结束就是结束,不能从某个角度来说。当然咯 角度多了自然说法就多了,比如说: 哪天赵老师百年之后我们也可以这样说“赵老师永远活在我们心中”。(^_^)
[Quote=引用 24 楼 的回复:]

关于楼主本人的生命周期。
就算楼主百年后变为灰烬或更小的原子了,从某种角度还是可以说楼主的生命周期远没有结束。
试问又有哪个人能肯定他现在的生命的某些部分不是由他的八辈祖宗的某些部分延续下来的呢?
(^_^)
[/Quote]
加载更多回复(26)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧