今天又做蒙了一道题,把思考和实验记录下来。
struct sk{
int a; float b;}data;
int *p;
若要使p指向data中的a域,正确的赋值语句是
p=&a; p=data.a; p=&data.a; *p=data.a
前两个可以很容易看出错误之处,a是结构体内的变量,需要加上结构体来限制,p是指针类型,不能赋给int类型,后两个好像没什么毛病,一个是把data成员a的地址给p,另一个是将data成员a的值作为p指向的内容,但答案确实前者。
经过实验我发现确实是p=&data.a
正确,后者输出会为空,也就是并没赋上值,结果展示如下:
正确输出如下:
同时我也发现了问题,为啥写成*p=data.a
时连正常输出data.a也不成了,并且编译也没错啊,实在找不到这句话的逻辑错误,我把结构体的内容改成常规变量重新实验,结果展示如下:
可以看到p指针指向的内容的的确确被修改了,也就是说换成常规变量后代码是执行成功了的,那为什么在结构体内就不成呢?
经过一番交流探索发现,首先输出不出来的原因是因为指针未初始化,此时直接解引用会覆盖之前原有的内容,导致程序莫名其妙的错误;另外我思考的和题目的侧重点不同,题目要求是指向a的域 而我更多关注只是指针指向值的变化,也就是题目是要求指针地址的变化,而我只实现了指针指向内容的变化,指针本身未变,新的实验和结果如下:
首先可以看到经过初始化后的指针已经能够正确输出结构体的值,但是使用*解引用赋给的值只是改变了指针指向的内容,而指针地址未变,使用&取地址才能改变指针的地址。
总结
&引用可以使指针指向该内容,*可以使指针指向的内容更改,结合赋值语句都可以理解为为原有数据创建分身,只不过一个是指向原数据的分身,对分身的操作等同于操作原体,另一种则相当于是给数据做了个备份,故采取这种方法也失去了我们使用指针的原本含义。
此外,坚持创建即初始化这个好习惯,要不然可能引发未知的错误。