一 指针定义
一个对象的指针就是该对象的地址
二 数组与指针
1 用指针访问数组的元素
假设指针p已指向a,访问数组的方法有下标法,地址法,指针法,如下表:
下标法 | 地址法 | 指针法 | |
第K个元素 | a[k] | a[a+k] | a[p+k] |
第k个元素的地址 | &a[k] | a+k | p+k |
指针访问数组要注意:
@指针的指向
@指针变量是变量,可以改变,而数组名是指针常量定义后便不可以改变
2 指向多维数组的指针(以二维数组为例)
设有整型二维数组a[3][4],设首地址为1000
则数组a可分解为三个一维数组,即a[0]、a[1]、a[2]。每一个一维数组又含有四个元素。
a[0]数组,含有a[0][0],a[0][1],a[0][2],a[0][3]四个元素。
数组及数组元素的地址表示如下:从二维数组的角度来看,a是二维数组名,a代表整个二维数组的首地址,也是二维数组0行的首地址,a+1代表第一行的首地址
同理,a+1是二维数组1行的首地址,等于1008。a[1]是第二个一维数组的数组名和首地址,因此也为1008。&a[1][0]是二维数组a的1行0列元素地址,也是1008。因此a+1,a[1],*(a+1),&a[1][0]是等同的。
由此可得出:a+i,a[i],*(a+i),&a[i][0]是等同的。
此外,&a[i]和a[i]也是等同的。因为在二维数组中不能把&a[i]理解为元素a[i]的地址,不存在元素a[i]。C语言规定,它是一种地址计算方法,表示数组a第i行首地址。由此,我们得出:a[i],&a[i],*(a+i)和a+i也都是等同的。
另外,a[0]也可以看成是a[0]+0,是一维数组a[0]的0号元素的首地址,而a[0]+1则是a[0]的1号元素首地址,由此可得出a[i]+j则是一维数组a[i]的j号元素首地址,它等于&a[i][j]。
访问多维数组及其地址的方法:
下标法 | 地址法 | |
a[i][j]元素 | a[i][j] | *(*(a+i)+j)或*(a[i]+j) |
a[i][j]元素地址 | &a[i][j] | *(a+i)+j或a[i]+j |
三 字符串与指针
1 一个字符型指针可以保存一个字符型变量的地址所以可以利用字符型指针指向一个字符串。例如:
char *p;
p="C Language"; /*尽管使用赋值语句,也不会赋值字符串,而是赋值首地址*/
使用指针变量输出字符串。例如:
printf(%s",p);
或用循环语句逐个输出。
2 字符指针变量与字符数组区别
@储存方式不同
@运算方式不同
@赋值方式不同
四 函数与指针
1 指针作为函数参数
当函数参数是指针变量时,形参为指针变量,而实参为地址表达式将实参的地址拷贝给形参,由于传递给形参的是地址,函数
可以对此地址访问与主调函数共享此空间。
2 数组名作为函数参数
因为数组名代表的地址,所以数组名作为参数实际是将数组首地址传递给形参,即实参数组和形参数组占用同一内存单元
3 指针作为函数的返回值
4 指向函数的指针
一个函数在编译时被分配一个入口地址。这个入口地址就称为函数指针。可以用一个指针变量指向函数,然后通过该指针变量调用此函数。
声明格式
数据类型 (*指针变量名)(形参列表);
@数据类型是指针变量所指向的函数返回值的类型
@形参列表是指针变量所指向函数的全部参数,其格式遵循函数形参的声明格式要求
五 指针数组
指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。
指针数组是数组元素为指针的数组(例如 int *p[3],定义了p[0],p[1],p[2]三个指针),其本质为数组。
六 指针数组
指针数组:即用于存储指针的数组,也就是数组元素都是指针
数组指针:即指向数组的指针
还要注意的是他们用法的区别,下面举例说明。
int* a[4] 指针数组
表示:数组a中的元素都为int型指针
元素表示:*a[i] *(a[i])是一样的,因为[]优先级高于*
int (*a)[4] 数组指针
表示:指向数组a的指针
元素表示:(*a)[i]