为了账号安全,请及时绑定邮箱和手机立即绑定

指针初始化的问题

指针初始化的问题

慕粉1600176492 2016-12-12 21:29:23
例子(1) #include"stdio.h"  int main()  {    int a,c,*t;     int *p=&a,*q=&c;     *t=*p;     *p=*q;     *q=*t;    return 0;  }  例子(2)  #include"stdio.h"   int main()   {      int a,c,*t=0;      int *p=&a,*q=&c;      *t=*p;      *p=*q;      *q=*t;      return 0;   }   //请问这两个例子有什么区别吗?为什么有的书上写着第一种情况如果p指向了某一个重要的数据,那么就会被改变,   //我初始化的概念不太清楚,是不是定义的时候才算初始化,第一种情况是不是比较危险,那第二种方法会不会更好点呢?
查看完整描述

3 回答

已采纳
?
朕日理万机

TA贡献27条经验 获得超28个赞

两个实现其实都非常危险。不知道这个例子是不是你为了简化代码自己删减了,还是教科书上原本就这么写的。

先说第二个。int *t = 0,在现代编译器里,意思是把空指针赋值给t,空指针是不允许解引用的,你如果运行一下你第二个代码,应该会得到一个segmentation fault。(感谢@onemoo 网友指出,C语言标准中把0赋值给指针,相当于把NULL赋值给指针。C++11引入了nullptr关键字,从此建议用它作为空指针)。总之空指针唯一的作用是用来比较,其他操作都应该避免。你可以把指针初始化为空,然后在运行时把某个地址赋给它,然后要操作时先判断是否为空。

然后说第一个变量默认初始化,如果是静态或者全局变量,比如不属于任何函数体中的变量,int会初始化为0,指针会初始化为空指针。而你的代码,不管a, c, *t都是函数中声明的局部变量(存在于栈上),会用某些不确定的值去初始化它们。a和c还好一点,它们会有不确定的值,你如果后面不依赖于a和c做什么重要的事情就没关系。而t会指向某个不确定的地址,它可能关系到别的代码,你在中间改变t指向的地址的值,就是很危险的事情,可能会影响别的调用。所以真正危险的不是p,而是t。


查看完整回答
2 反对 回复 2016-12-14
  • onemoo
    onemoo
    实际上,C标准规定,整型常量0就是NULL指针,所以这不是“未定义”或“未指定”行为
  • 朕日理万机
    朕日理万机
    C语言里的确是有宏定义#define NULL 0。不过从c++11开始不建议用NULL 和 0作为空指针了,而改用nullptr关键字。原因我也不太清楚,有说法是可能引起函数重载的混乱。不过的确如你所说,大部分情况下0就是作为空指针使用
  • onemoo
    onemoo
    是的,C++11不再使用0,而增加了nullptr作为null pointer常量值。 但C标准(至少在C99及C11标准中都是如此)规定整型常量0是null pointer常量值,且在<stddef.h>定义为NULL宏。所以使用0作为null pointer在C中仍是安全且确定的。
?
onemoo

TA贡献883条经验 获得超454个赞

抱歉,题主,我之前的回答有误,谢谢 @朕日理万机 指出错误。你可以看帖子中我们俩的讨论。


具体来说,我回答中的“但是你在真正使用 t 之前就向 t 赋予了适当的值(通过 p 使其指向 a)”说错了

*t=*p  并不是让 t 指向 a,这语句只是在 t 所指的内存中存入 p 所指的值(也就是 a 的值)。

那么在第一例中,这时 t 还没有适当的值,所以可能会引起严重的问题。

而在第二例中,t 是个NULl指针,解引用NULL指针会直接引起segmentation fault。


要使用指针,一定要确保其指向适当的、有意义且安全的地址。

对于你这里的代码,如果一定要通过指针来交换a、b值,那么也要先让 t 指向一个安全可使用的内存,比如:

  • 你可以再定义一个int c,然后让 t 指向 c

  • 也可以用 malloc(sizeof(int)) 申请一块内存,让 t 指向这里

这样就可以确定 t 指向的是安全可用的内存,然后再利用 *t 来交换 *p *q 就没问题了。


最后,请采纳 @朕日理万机 的回答。

查看完整回答
1 反对 回复 2016-12-14
?
onemoo

TA贡献883条经验 获得超454个赞

就这两个简单的代码来说,没有区别!

例子1中,你先定义了int指针 p,随后 p = &a; 把变量 a 的地址赋值给 p,也就是 p 会指向 a。 像这样在定义时没有指定初值的话,p 的值是不确定的!也就是 p 指向什么是不确定的。你这时不应该使用 p 的值,当然你后面为 p 赋了确定的值后就没有关系了。

例子2中,你在定义指针 p 的同时提供了初值,所以定义好的 p 的初值就是指向 a 的。

所以从结果来看这两个例子并没有什么区别。


“第一种情况如果p指向了某一个重要的数据,那么就会被改变”

——这个代码中显然 p 开始时并没有指向重要数据。另外,假如 p 之前指向了什么,那么“就会被改变”,这指的是什么被改变??  

p 被改变吗? 那当然了,p=&a 这就是为 p 赋值啊,当然会改变 p 的指向了。 但这并不会改变被 p 所指的对象的值!  所以也没什么关系。 而且你既然已经要为 p 赋值了,就说明你已经打算让 p 指向新的东西了,原来所指的东西重不重要跟 p 也没关系了。

查看完整回答
反对 回复 2016-12-12
  • 慕粉1600176492
    慕粉1600176492
    不好意思,上次那个问题不正确,我重新举了两个例子,帮忙看一下。
  • onemoo
    onemoo
    那我再回一贴吧。不过,这两个新的例子和老的没区别呀...
  • 3 回答
  • 0 关注
  • 1888 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信