指针(一)
经过前面漫长的c语言学习,终于进入了C语言中最核心,最重要的部分啦!其实对于前面的知识,自己都有所了解,必境C语言也是一直在学(只是没学通而已(∩_∩)),但是通过写博文的方式,我发现最好的一个地方就是它能够让你很踏实地去学习,摒弃浮燥,因为你写出来的东西都是自己亲自验证过的,强制让自己把所学的东西全部动手实践出来,写博文的另外一个很大的劣势,那就是比较费时间,如果你不写博文,可能对于我之前c语言的基础知识的学习可能一两周就学完了,而如果加上写博文,时间就得翻倍了,但是:我觉得这些小时间的"浪费"是非常值得的,因为你会学得扎实!所以,我会一直坚持下去的,好了,话不多说,正式进入非常期待,也非常容易犯迷糊的C语言“指针”之旅啦!
什么是指针:
![](http://images0.cnblogs.com/blog/324374/201312/08134824-6d70ff8b17984a748d1cb8c5a1a9ac40.png)
![](http://images0.cnblogs.com/blog/324374/201312/08140559-c5fddd4b8d9543aaac396b39bbd15d8e.png)
![](http://images0.cnblogs.com/blog/324374/201312/08140951-e8b514bbb72d4377af737e689b147f38.png)
下面通过代码来初探下指针:
![](http://images0.cnblogs.com/blog/324374/201312/08142129-b93195a96d874f0182dc0a878a4a22cf.png)
看结果:
![](http://images0.cnblogs.com/blog/324374/201312/08142414-8046753e24bb453489523180131a41ba.png)
从输出的地址来看,这两个变量都是在栈上分配的,ec和e8刚好差一个整数的大小,说明这两个地址是连续的,且linux中栈地址增长是从高地址往低地址
如果在两个变量声明之间再加入一个变量呢?
![](http://images0.cnblogs.com/blog/324374/201312/08142831-ffa087cf0a444a78a52eeb22d1d34933.png)
![](http://images0.cnblogs.com/blog/324374/201312/08142918-1ea09c54c63c40af83081054985c814e.png)
7c、78、74刚好是四个字节连续的。
上面演示的指针是指向一个栈区,实际上,指针可以指向内存的任何区域(堆区、数据段.......):
![](http://images0.cnblogs.com/blog/324374/201312/08144114-5cd7c3896de344d0a0da46952c5931f9.png)
运行结果:
![](http://images0.cnblogs.com/blog/324374/201312/08144333-c841a5082ed84332b54f2b690901bb08.png)
&和*运算符:
![](http://images0.cnblogs.com/blog/324374/201312/08144928-84e8cd54874f413b9e0b237316d0905c.png)
![](http://images0.cnblogs.com/blog/324374/201312/08145948-a3c4e7f22c0f40f28695d432e4aeb532.png)
![](http://images0.cnblogs.com/blog/324374/201312/08150152-1ea5b3f7e1f5438daa7aba1eb9aa29cc.png)
值传递【比较经典的问题,也比较简单】:
#include <stdio.h> //值传递,最终不会影响原值 void swap(int x, int y) { int tmp = x; x = y; y = tmp; } int main(void) { int a = 100; int b = 200; printf("before swap: a=%d b=%d\n", a, b); swap(a, b); printf("after swap: a=%d b=%d\n", a, b); return 0; }
输出结果:
指针与函数参数:【比较经典的问题,也比较简单】
#include <stdio.h> //指针传递,形参的改变最终会影响实参 void swap(int* px, int* py) { int tmp = *px; *px = *py; *py = tmp; } int main(void) { int a = 100; int b = 200; printf("before swap: a=%d b=%d\n", a, b); swap(&a, &b); printf("after swap: a=%d b=%d\n", a, b); return 0; }
输出:
空指针:
空指针NULL,是一个特殊的指针,表示不指向任何东西。NULL实际上是用(void*)0表示的。
![](http://images0.cnblogs.com/blog/324374/201312/08151729-9630f5703df141be98b91bed9f87e211.png)
![](http://images0.cnblogs.com/blog/324374/201312/08151841-5e1f510da76d44589e566d91e3922f52.png)
![](http://images0.cnblogs.com/blog/324374/201312/08151918-2333bd0fb13149a998aa7a596df631b0.png)
int* p = NULL;
*p //这种操作是不允许的。
通用指针【上面已经接触到了】:
在这之前,需理解一下指针类型:
![](http://images0.cnblogs.com/blog/324374/201312/08152558-951bd3b684a54f3ab3cf26a6564892e9.png)
![](http://images0.cnblogs.com/blog/324374/201312/08152457-1b877ab613984d59b17199581c8272c3.png)
指针算术运算:
我们来想一个问题:
对于变量,有不同的类型,是因为不同数据类型的空间大小是不一样的,是为了内存的分配,如:
short a;//占2个字节 int b;//占4个字节 double c;//占8个字节
但是:对于不同类型的指针变量,它们占用的空间都是相同的:
short* a;//占四个字节 int* b;//占四个字节 double* c;//占四个字节
那为什么不用一个指针类型来含盖所有不同类型的指针呢?原因就是为了:指针算术运算
所以,从上图来看,指针的加法支算,并非简单的地址+1,而是根据不同的数据类型,来偏移一个数据类型,这也就是为什么指针需要指定类型的原因。
好了,指针的初步了解就到这,之后会慢慢深入,下回见!