在学C语言的途中,不免会遇到很多难题。相信学C和C++的同学们对指针一定有所耳闻,它也是大家在日后学数据结构的基础。
每一个变量都有一个内存位置,每一个内存位置都定义了可使用 & 运算符访问的地址,它表示了在内存中的一个地址。指针有时也是个普通的变量,不过和其他变量不同的是,指针中装的是地址,大多数情况下是其他变量的地址。
在课程中,老师很喜欢用以下式子来定义指针:
int a = 5;
int *p = &a;
很多同学此时就有了疑问:&a也就是a的地址到底赋值给了p还是*p?
重点来了:此时的&a赋值给的是p!!!或者我们可以换以下写法,看的更为清晰。
int a = 5;
int* p = &a;
可以看出,这个写法将 int 与 * 连在一起写了,我们便可以理解为:
声明一个变量p,这个变量p的类型是 int* (注意,是int*不是int),然后将a变量的地址赋值给了p变量,也即 “指针p指向a” 。
但是,与其他变量不同,int * 类型的变量不能直接连续声明。下面用 p 与 q 进行对比:
int* p,q;
如上,只有 p 为 int* 类型,q 依然是普通 int 类型的整型变量。
int* p,*q;
如上,此时的 p 与 q 才为 int* 类型的指针。
以下几种写法完全等价,看个人习惯(大部分人习惯的是第一种,但我个人觉得第二种是最容易理解的):
int *p1;
int* p2;
int * p3;
int*p4;
所以我们再来对比一下指针的几种赋值:
第一种(声明时赋值):
int a = 5;
int* p = &a;
第二种(声明后赋值):
int a = 5;
int* p;
p = &a;
第三种(连续赋值):
int a = 5,*p = &a;
第三种赋值需要单独说一下:此时&a赋值给的依然是p而不是*p!!!虽然此时看起来非常像 *p = &a,但实质上是 p = &a。此时只不过先用 int 声明了一个普通变量,后一句把 int* 的 int 省略了,与第一种声明时赋值完全相同。
此时会发现这三种除了写法不同以外,作用却是完全相同的。
易错误区一:
int a = 5;
int* p;
// 错
*p = &a;
错误原因:*p的类型是 int 类型,p的类型才是 int*,此时等于号右边是int*类型,等于号左边是int类型,会报警告!(类型不同强制转换的警告,且p此时不但没成功指向a,还成了野指针)
易错误区二:
int a = 5;
// 错
int p = &a;
错误原因:p 此时的类型是 int 类型,此时等于号右边是int*类型,等于号左边是int类型,会报警告!(类型不同强制转换的警告,且p此时不是指针变量,而是普通的 int 变量)
易错误区三:
int a = 5;
// 错
int *p = 5;
错误原因:p的值没有初始化。p就跟其他普通成员变量一样,需要初始化。否则,p此时谁也不知道存的什么值,用*取内容程序也一定是有问题的。像此类p不知道指向什么地方,就进行操作的指针,叫做野指针。
总结
可以用以下两种方法去理解指针变量赋值问题
第一种:
int *p=&a; p指针在声明时,*仅仅只起着说明p是指针变量的作用,这种写法更强调了 p 指向的区域是一个 int 类型的区域。所以 a 的地址赋值给的是p,而不是*p。
第二种(前文提到的方法):
int* p=&a; p指针在声明时,类型为 int* ,这种写法更强调 p 的类型为 int*。所以,将 a 的地址赋值给一个 int* 类型的变量,而不是赋值给 *p。
其他当然还有很多指针:char* ,int* ,long* ... 以此类推,本例仅用 int* 做演示。星号前面的类型是这个指针指向区域的类型,可以是C语言中的任何数据类型。
如果有帮助就给个赞再走吧!!!