指针重要吗
指针在C语言中占据着重要的地位,指针有效的取代了在低端语言(如汇编语言与机器代码)直接使用内存地址。指针又比较贴近硬件,编译器能够很容易的将指针翻译为机器代码,这使指针操作时的计算机负担较少,同时简化一些C语言编程任务,能够提高程序的运作速度。
正是由于比较贴近硬件,并且指针可以与C语言中的其他数据结构(如数组、链表、结构体、函数)进行结合,可以说是贯穿了整本C语言。使得对于初学计算机编程的人理解起来有些难度。本文将结合图像和示例对指针的知识进行整理汇总,记录指针的学习过程,让指针也变得简单起来。
指针的定义
指针(英语:Pointer)在百科中给出的定义是编程语言中的一类数据类型及其对象或变量,用来表示或存储一个存储器地址,这个地址的值直接指向(points to)存在该地址的对象的值。
从这个定义中可以得到以下信息,首先指针也是一种数据类型,就像我们前面学到的int,char,float,double等基础数据类型。同样的指针也可以像其他基础数据类型一样定义变量,不同的地方在于指针变量中保存的是一个存储器的地址。
(补充:程序中所有的数据都是存储在内存中的,内存被分成一个个的内存单元,每个内存单元又有一个地址。系统内存就像是带有门牌号的小房间,如果要使用某个房间,就需要得到房间的门牌号。而指针变量存储的就是门牌号,即也就是存储器地址)。
指针定义变量的方式如下:
1 | int *a,b=5; |
- int *为整型指针数据类型,定义了一个存储整型变量存储地址的指针变量a
- char *为字符型指针数据类型,定义了一个存储字符型变量存储地址的变量c
- float *为单精度浮点型指针数据类型,定义了一个存储浮点型变量存储地址的变量f
指针变量的赋值
两个指针运算符:
地址运算符&
取内存中变量的地址,例如&b,值为整型变量b的内存地址。取值运算符* 获取指针变量所指向变量的值,例如a,值为5。(注意与int *中的\相区别)
a = &b;代表取出整型变量b的地址赋值给a,图中简单表示为2000赋值给a,即a指向变量b,a中存储了变量b的内存地址2000。指针变量c和f的赋值也一样如图所示。
这里要区分两个容易混淆的概念:
- 指针的类型
指针的类型是指针变量本身的类型,指针变量在内存中占据4个字节,存储32位的内存地址码。
- 指针变量a的类型为int *
- 指针变量c的类型为char *
- 指针变量f的类型为float *
- 指针指向的类型
指向的类型是当前指针存储的内存地址中所存储变量的类型。
- a指向的类型为int
- c指向的类型为char
- f指向的类型为float
指针与一维数组
我们都知道数组名是代表数组首元素地址的符号常量,而指针变量又可以存储地址,所以数组不仅可以通过数组名+下标的方式访问,也可以通过指向它的指针变量来访问。
指向数组的指针变量
我们前面定义的指针变量都是指向一个基础数据类型的变量,指向数组的指针变量定义方式也类似。
1 | int c[5]; |
表达式(p+1)或(c+1)都代表数组元素c[1],其中p+1和c+1都代表c[1]的地址&c[1]。
数组名称c为常量,故任何对数组名称赋值的操作都是错误的。
C语言不会对地址操作做越界检查,故数组越界不会报错,这也是程序容易出错的地方。
1 | int (*p)[5]; |
- 上面第一个定义方式为,首先计算(),*p代表p是一个指针变量,然后是[5],代表p指向一个大小为5的数组,最后int,代表p指向的是一个存储整型变量的数组。即定义数组指针p,指向一个存储5个整型元素的数组。
- [5]的优先级要高于*,故p首先是一个大小为5的数组,其存储的数据类型为指针变量,而指针指向的数据类型为整型int。
指针与二维数组
定义二维整型数组如下
1 | int a[3][3] = {{14,16,19},{22,55,88},{33,54,32}}; |
二维数组a的元素是按行进行存储的,可以将a数组的3行看成3个分数组:a[0],a[1],a[2]。每个分数组是含3个列元素的一维数组。
如下图所示:
数组名a是指向0号分数组的指针常量,值为2000,同样不能够给a赋值。a+0,a+1,a+2则分别表示0号分数组,1号分数组,2号分数组,对应存储器地址值为2000,2004,2008。
其中a[0],a[1],a[2]为三个一维分数组的数组名称,这三个数组名存储的地址又分别指向a[0][0],a[1][0],a[2][0],对应的数值为3000,3006,3012。
a[0]+1和a[0]+2则是分别指向a[0][1],a[0][2]的指针常量,对应的地址值为3002,3004。
虽然a与a[0]的地址都是2000,但是并不等价,a的基类型字节数为4,a[0]为2,也可以从a+1与a[0]+1的不同结果看出。
以下是二维数组不同表示形式的含义与内容: