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。
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 就没问题了。
最后,请采纳 @朕日理万机 的回答。
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 也没关系了。
添加回答
举报