指针的算数运算
+
和 -
可以将指针向前或向后移动 n 个字节,n 取决于指针的类型在此计算机中占用的字节数,使用的方法和普通变量一样。两个指针相减则可以得到两指针间的距离,这种运算只有在两个指针指向同一个数组中的元素时候有意义,可以计算出两个指针指向的元素之间相隔多少个元素
指针也可以使用 ==
& !=
& <=
& <
等运算符进行比较,但也是只有当两个指针指向同一个数组的时候这种比较才是有意义的
*
和 ++
组合的表达式的含义
表达式 | 含义 |
---|---|
*p++ 或 *(p++) | 表达式值为 *p ,之后自增 p |
(*p)++ | 表达式值为 *p ,之后自增 *p |
*++p 或 *(++p) | 先自增 p ,表达式值为自增后的 *p |
++*p 或 ++(*p) | 先自增 *p ,表达式值为自增厚的 *p |
下面是指针使用运算符的例子:
...
int a[10], *p;
p = &a[0]; //指针 p 指向数组的第一个元素
*p = 5; //a[0] = 5
p += 3; //指针向后移动了 3 个单位,现在指向 a[3]
*p = 3; //a[3] = 3
p -= 2; //指向 a[1]
*p = 7; //a[1] = 7
*++p = 9; //a[2] = 9
int *q;
q = p + 6; //q 指向 a[8]
int i;
i = q - p; //i = 6
数组名作指针
C语言中,指针和数组很多方面都是一样的。比如数组名可以作为指针,关于数组 a[10]
,数组名 a
就是指向这个数组第一个元素的指针,即 *a
就是 a[0]
,也可以当做个指针传递给函数,虽然 a
像是个指针,但是不能像指针那样自加自减改变自己指向的地址。那如何使用这个数组名来访问数组呢?答案是:*(a + n)
这等价于 a[n]
那么指针应该也能看做数组才对吧。是的!*(p + n)
等价于 p[n]
下面的例子是数组和指针之间转换的简单运用:
#include <stdio.h>
#define MAX 3
void print_array(int *, int);
int main() {
int a[MAX];
for (int i = 0; i < MAX; i++)
*(a + i) = i;
print_array(a, MAX);
return 0;
}
void print_array(int *p, int n) {
for (int i = 0; i < n; i++)
printf("%d ", p[i]);
printf("\n");
}
指针遍历数组
先创建一个 3×3 的数组 a
...
int a[3][3] = {{1, 2, 3},
{4, 5, 6},
{7, 8, 9}};
遍历整个数组
...
int *p = &a[0][0];
for (int i = 0; i < 9; i++)
printf("%d ", *p);
...
遍历整个数组的元素是最简单的了,可以把二维数组想象成一个一维数组,指针不断向后移动就可以遍历完整个数组
遍历数组的行
...
int *p = &a[j][0]; //j 为要遍历的行的下标,此处也可以为 int *p = a[j];
for (int i = 0; i < 3; i++)
printf("%d ", *p++);
...
若要遍历某一行的元素,只要让指针指向这一行的第一个元素的地址,然后就和遍历一维数组一样了,长度限为一行的长度即可
遍历数组的列
...
int (*p)[3] = &a[0]; //此处也可以为 int (*p)[3] = a;
for (int i = 0; i < 3; i++)
printf("%d ", (*p++)[j]); //j 为要遍历的列的下标
...
int (*p)[3]
中 p
不是指向 int
变量的指针, 而是指向 int [3]
(一个长度为 3 的整形数组)的指针,称为数组指针或行指针,p
自增 1 将向后移 3 个 int
的地址,在这里相当于移动了一行
因为 p
是 int (*)[3]
类型的指针,所以 *p
相当于一个长度为 3 的整形数组,所以可已取下标 (*p++)[j]
二维数组其实也是一维数组,但是它的每个元素都是一个一维数组。前面我们讲到数组名可以作指针使用,二维数组也适用但有所不同,二维数组 a[][]
,a
(即 &a[0]
)可以作指向这个数组第一个元素的指针,这样听起来和一维数组没什么区别呀,但其实这所谓的第一个元素是一个一维数组,这个指针的类型是 int [N]
类型,而 a[0]
(即&a[0][0]
)才是指向数组第一个元素的 int
类型的指针,在作为函数参数时要注意指针的类型
#include <stdio.h>
void fun(int *p);
int main() {
int a[3][3];
...
fun(a[0]); //ok
fun(a); //error
return 0;
}
int fun(int *p) {
...
}