Bootstrap

C语言 指针入门最大的误区:int *p=&a;a的地址赋值给的是p不是*p

        在学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语言中的任何数据类型。

如果有帮助就给个赞再走吧!!!

;