免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4446 | 回复: 11
打印 上一主题 下一主题

[C] 一道关于局部变量的练习题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-02-11 11:41 |只看该作者 |倒序浏览
Unix 高级环境编程中有一道练习题7.10,说是让判断下面的程序是否正确,
int f1(int val)
{
        int num = 0;
        int *ptr = #

        if (val == 0) {
                int val;
                val = 5;
                ptr = &val;
        }
        return (*ptr + 1);
}

然后给出的答案是:
7.10 The  code  is  incorrect,  since  it  references  the  automatic  integer val through  a
pointer after the automatic variable is no longer in existence. Automatic variables
declared after the left brace that starts a compound statement disappear after the
matching right brace.
“代码不正确,因为if中的局部变量val只在if的作用域里有效(大括号中间的那段),这里的指针引用超出了范围”


但我觉得这里有问题:
局部变量是存在栈中的,这些变量在一个函数的范围内都是固定地址,所以这个引用没有错。

论坛徽章:
12
巳蛇
日期:2013-09-16 15:32:242015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之约旦
日期:2015-02-11 14:38:37双鱼座
日期:2015-01-05 11:05:47戌狗
日期:2014-12-08 09:41:18戌狗
日期:2014-08-15 09:29:29双子座
日期:2014-08-05 09:17:17卯兔
日期:2014-06-08 15:32:18巳蛇
日期:2014-01-27 08:47:08白羊座
日期:2013-11-28 21:04:15巨蟹座
日期:2013-11-13 21:58:012015年亚洲杯之科威特
日期:2015-04-17 16:51:51
2 [报告]
发表于 2014-02-11 11:47 |只看该作者
本帖最后由 zhaohongjian000 于 2014-02-11 11:49 编辑

作用域是作用域,不要拿生存期考虑作用域。比如,

  1. void func1()
  2. {
  3. static int x;
  4. }

  5. void func2()
  6. {
  7. x = 1;
  8. }
复制代码
func1中的x是静态变量,在整个程序执行期间都存在,但还是无法在func2中访问。

论坛徽章:
769
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
3 [报告]
发表于 2014-02-11 12:01 |只看该作者
回复 1# fireaxe

楼主加个main验证下就知道了 f1()返回值永远为1.

   

论坛徽章:
1
摩羯座
日期:2013-12-19 10:04:07
4 [报告]
发表于 2014-02-11 12:24 |只看该作者
本帖最后由 lin5161678 于 2014-02-11 12:25 编辑

void foo()
{
    int i;
    {
        int j;
    }
    int z;//对于这段代码 j 和 z(或 i)的地址可能是同一个地址  内存可能的确没释放 但是 可能被其他对象占据 所以说 使用超出作用域的val是错误的 这样讲 能明白吗?

}

论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
5 [报告]
发表于 2014-02-11 13:46 |只看该作者
Herowinter 发表于 2014-02-11 12:01
回复 1# fireaxe

楼主加个main验证下就知道了 f1()返回值永远为1.

f1()返回值永远为1,这个说法不对哦~~,呵呵

论坛徽章:
0
6 [报告]
发表于 2014-02-11 15:26 |只看该作者
本帖最后由 fireaxe 于 2014-02-11 15:27 编辑

回复 2# zhaohongjian000

这样连编译都过不了吧。
原书的例子中通过保存地址的方式突破了局部变量的作用域,重点还是是否这块内存会被其他变量使用。
如果是使用加了static的局部变量,应该是可以在其他函数中使用的。
  1. int *tmp=NULL;

  2. void func1()
  3. {
  4.         static int x=123;
  5.         tmp = &x;
  6. }

  7. void func2()
  8. {
  9.         printf("%d\n", *tmp);
  10. }

  11. int main(int argc, char *argv[])
  12. {

  13.         func1();
  14.         func2();
  15. }
复制代码
output:
123

论坛徽章:
0
7 [报告]
发表于 2014-02-11 15:34 |只看该作者
回复 3# Herowinter


原书作者的意思应该是说这种做法不对,有可能会产生错误,但这个例子本身其实无法让这中错误出现。
入参是0时会返回6的。

论坛徽章:
12
巳蛇
日期:2013-09-16 15:32:242015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之约旦
日期:2015-02-11 14:38:37双鱼座
日期:2015-01-05 11:05:47戌狗
日期:2014-12-08 09:41:18戌狗
日期:2014-08-15 09:29:29双子座
日期:2014-08-05 09:17:17卯兔
日期:2014-06-08 15:32:18巳蛇
日期:2014-01-27 08:47:08白羊座
日期:2013-11-28 21:04:15巨蟹座
日期:2013-11-13 21:58:012015年亚洲杯之科威特
日期:2015-04-17 16:51:51
8 [报告]
发表于 2014-02-11 15:42 |只看该作者
fireaxe 发表于 2014-02-11 15:26
回复 2# zhaohongjian000

这样连编译都过不了吧。


我没看清题目。原题中,出了作用域之后if内的val怎样就没有保证了。val存在于栈上,并且在整个函数中都有效只是对于编译器生成代码的方式的推测,实际上如果不对val取地址,val可能只存在于寄存器中。同样的,当val存在于栈上时,它的内存也可能在出了if之后被用于其它用途。

论坛徽章:
769
金牛座
日期:2014-02-26 17:49:58水瓶座
日期:2014-02-26 18:10:15白羊座
日期:2014-04-15 19:29:52寅虎
日期:2014-04-17 19:43:21酉鸡
日期:2014-04-19 21:24:10子鼠
日期:2014-04-22 13:55:24卯兔
日期:2014-04-22 14:20:58亥猪
日期:2014-04-22 16:13:09狮子座
日期:2014-05-05 22:31:17摩羯座
日期:2014-05-06 10:32:53处女座
日期:2014-05-12 09:23:11子鼠
日期:2014-05-21 18:21:27
9 [报告]
发表于 2014-02-11 15:55 |只看该作者
回复 7# fireaxe
不好意思,看得不是太认真,
感觉问题在于ptr指向的内存
在f1调用过程中会用于其他用途吗?


   

论坛徽章:
0
10 [报告]
发表于 2014-02-11 16:26 |只看该作者
回复 4# lin5161678

又做了个实验,确实是这样,看来还是我对栈的分配理解有误。
根据我原来的理解,堆栈是在进入函数时就分配好的,从反汇编后的代码看,前两条指令就是为这个函数分配所需的堆栈。所以我认为,在这个函数的作用域里,所有的变量都有固定的地址,不会互相冲突。
从刚才做的实验看,堆栈确实是入口时分配的,但变量的地址却不是固定的。看来即使是函数内部的大括号,也会影响堆栈的分配。

但如果想引发这种错误,需要如下情况
  1. void foo()
  2. {
  3.     int i;

  4.     {
  5.         int j;
  6.     }

  7.     {
  8.         int z;
  9.     }
  10. }
复制代码

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP