Part 0:为什么要写这篇文章
C语言中的指针是C语言的精髓,也是C语言的重难点之一。
然而,很少有教程能把指针讲的初学者能听懂,还不会引起歧义。
本文章会尝试做到这一点,如有错误,请指出。
我们先抛开指针不谈,来讲一个小故事:
一天,小L准备去找小S玩。但是小L不知道小S的家住在哪里,正当他着急的时候,他看到了一个路牌,上面写着:小S的家在神仙小区403
哦,真的是要素过多。为什么这么说?
小L和小S:我们可以看做是两个变量/常量。
小S的家:这里可以看做是变量/常量小S的地址。
我们要搞清楚,每个变量/常量都和我们一样:我们每个人都有自己的家,正如变量也有自己的地址。通俗的理解,地址是给变量/常量来存放值的地点。
路牌:注意注意注意!这里就指出了变量/常量小S的地址:神仙小区403
事实上,我们等会会讲,输出一个变量的地址其实是个16进制的数字。
搞懂了上面,我们再来聊聊&
&这个符号我们一个不陌生,你最初用到应该是在:scanf("%d",&a)里边。
&叫做取址符,用来获取一个变量/常量的地址。
那么我们为什么要在scanf里边用&,不在printf里边用呢?
一开始我也很疑惑,后来我看到了这个例子:
你是一个新生,你要进教室。
但是你并不知道教室在哪里,这个时候你需要教室的地址。
下课了,你要出教室。
由于你已经在教室里了,你就不需要获取教室的地址就可以出去了。
一定要记住:指针就是个变量!
重要的事情说三次:
指针就是个变量!他储存的是地址!他自己也有地址!
指针就是个变量!他储存的是地址!他自己也有地址!
指针就是个变量!他储存的是地址!他自己也有地址!
为什么这么说?我们从指针的定义开始:
指针的定义方法:<类型名+*> [名称]
也就是说,指针的定义大概是这样的:
有的书上会这么写:
int *ip; float *fp; double *dp;这么写当然没问题,但是对于初学者来说,有两个问题:
有的初学者会把*p当做是指针名
有的初学者会把定义时出现的*p和取值时出现的*p弄混
指针他有没有值?有!我们会在下一节给他赋值。
既然他的定义方式和变量一样,他也有值,他为什么不是变量呢?
与指针相关的符号有两个,一个是&,一个是*。
先来聊聊&。
&我们上面讲过,他是来取地址的。举个例子:
%p用来输出地址,当然,你也可以写成%d或者%x。先不管这个,我们来看看他会输出什么:
那么也就是说,变量a和b的地址是000000000062FE1C和000000000062FE18
那么我们怎么把这个地址给指针呢?很简单:p = &a;,举个例子: #include <stdio.h> int main(){ int a = 10; int* p; p = &a; printf("a的地址:%p\n",&a); printf("指针p自身的地址:%p\n",&p); printf("指针p指向的地址:%p",p); }
得到输出:
a的地址:000000000062FE1C
指针p自身的地址:000000000062FE10
指针p指向的地址:000000000062FE1C
你发现了吗?如果我们有p = &a;,我们发现:直接输出p会输出a的地址,输出&p会输出p的地址(这就是为什么我一再强调p是个变量,他有自己的地址,正如路牌上有地址,路牌自身也有个地址一样)。
请注意!如果你的指针为int*,那么你只能指向int类型;如果是double*类型,只能指向double类型,以此类推当然,void*类型的指针可以转化为任何一种不同的指针类型(如int*,double*等等)
那么,我们来聊聊第二个符号*
*有两个用法。第一个在定义指针时用到,第二个则是取值,什么意思?看下面这个例子:
得到输出:
a的地址:000000000062FE1C
指针p自身的地址:000000000062FE10
指针p指向的地址:000000000062FE1C
指针p指向的地址的值:10