目录
1. 指针的算术运算
1.1 概述
1.2 C语言支持的算术运算类型
2. 指针的比较
3. 指针用于数组处理
4. 数组名与指针
4.1 用数组名作指针
4.2 数组取下标操作
4.3 惯用法
4.4 数组型实际参数
4.5 用指针作数组名
5. 指针和多维数组
5.1 正确理解二维数组的数组名
5.1.1 数组名可以被解释为指向数组第一个元素的指针
5.1.2 如果p指向对象x,那么*p就是对象x
5.1.3 如果x 是对象,那么&x得到指向该对象的指针
5.1.4 指针的算术计算以其指向的对象类型为单位
5.2 二维数组的降维处理
1. 指针的算术运算
1.1 概述
当指针指向数组元素时,C语言允许对指针进行算术运算(加法和减法)。通过这种运算可以用指针代替数组下标对数组进行访问
1.2 C语言支持的算术运算类型
C语言只支持3种格式的指针算术运算
① 指针加上整数
p 指向a[i],p + j 指向a[i + j]
② 指针减去整数
p 指向a[i],p - j 指向a[i - j]
③ 两个指针相减
当两个指针相减时,结果为指针之间的距离(用数组元素的个数来度量)
显然,只有两个指针指向同一个数组时,把他们相减才有意义
说明:这里需要强调,C语言只支持这3种运算,其余均报错。请看如下示例,
由于不能将两个指针相加,上述方法是不能取得数组中间位置元素的。需要做如下改进,
2. 指针的比较
只有在两个指针指向同一数组时,用关系运算符进行的指针比较才有意义,一般用于for循环遍历数组时
3. 指针用于数组处理
在用指针处理数组元素的语句中经常组合使用*(间接寻址)运算符和++运算符
4. 数组名与指针
4.1 用数组名作指针
可以用数组名作为指向数组第一个元素的指针
说明1:数组名被解释为指针常量,本质是因为系统没有为数组名分配存储空间。所以如下的代码是错误的,
int a[10];++a; // 错误!!!
说明2:从技术上说,数组的名字不是指针,C语言编译器会在需要的时候(表达式中的数组名)把数组名转换为指针
区别示例:对数组名用sizeof运算符和对指针用sizeof运算符
4.2 数组取下标操作
通常情况下,a + i 等同于&a[i],*(a + i)等价于a[i]
说明:数组的取下标操作可以看成是指针算术运算的一种形式,所以a[i] 和i[a] 是一样的
// 中间转换,像普通加法一样,指针和整数相加也是可交换的a[i] <---> *(a + i) <---> *(i + a) <---> i[a]
4.3 惯用法
for (p = a; p < a + N; ++p)sum += *p;
4.4 数组型实际参数
数组型实际参数的关键是没有复制数组本身
① 给函数传递数组所需的时间与数组的大小无关(因为只传递了地址值)
② 可以把数组型形式参数声明为指针
int find_largest(int a[], int n);int find_largest(int *a, int n);
特别注意:对于形式参数,声明为数组跟声明为指针是一样的,但是对变量而言,声明为数组跟声明为指针是不同的,示例如下,
int a[10];int *a;
③ 可以给形式参数为数组的函数传递数组的"片段",所谓片段是指连续的数组元素组成的序列。也就是说,在find_largest函数中,第一个参数指定的是要处理的数组元素的起始地址,第二个参数指定的是要处理的数组元素个数
4.5 用指针作数组名
int a[10];int *p = a;p[1] = 0;
本质:数组取下标只是一种地址计算方式
5. 指针和多维数组
5.1 正确理解二维数组的数组名
设有int a[NUM_ROWS][NUM_COLS];
我们结合上一章节中总结的指针变量4句圣经来解释二维数组的数组名
5.1.1 数组名可以被解释为指向数组第一个元素的指针
二维数组的元素是一维数组,所以二维数组名指向二维数组的第一行。其指针基类型为int (*)[NUM_COLS],在对其进行算术运算时,单位为一行
5.1.2 如果p指向对象x,那么*p就是对象x
因为二维数组的数组名a 指向其中的第一个一维数组,即指向第一行。所以*a 就是第一行这个一维数组,又因为一位数组名解释为指向其第一个元素的指针,所以*a 的类型为int *。考虑到*(a + i) 和a[i] 都是等价的地址计算方式,所以*(a + i) 和a[i] 均表示第i 行一维数组,类型均为int *
实验时间:为什么说*a 就是一维数组而不是一个简单的指针变量?
我们通过sizeof 运算符作用于数组名和指针变量时的不同行为来验证
sizeof(*a) 的结果是12 而不是4,正说明*a 表示的是一个一维数组名,而不是一个简单指针
5.1.3 如果x 是对象,那么&x得到指向该对象的指针
因为*(a + i) 和a[i] 均表示第i 行一维数组,所以&*(a + i) 和&a[i] 均为指向第i 行一维数组的指针,其类型为int (*) [NUM_COL]
5.1.4 指针的算术计算以其指向的对象类型为单位
a:指向二维数组的第一行一维数组,类型int (*)[NUM_COLS]
a[0] 或*a:指向第一行一维数组的第一个元素,类型为int *
在进行算术计算时, a + 1 越过一行,而a[0] + 1 越过一个int 型数据
5.2 二维数组的降维处理
处理一维数组的函数也可以处理二维数组的一行,进而扩展了这类函数的使用范围
设有int find_largest(int *a, int n)函数,用于求得一维数组中的最大元素,如果想求二维数组中的最大元素,可做如下调用,
find_largest(*a, NUM_ROWS * NUM_COLS);
本质:*a指针类型为int *