这一节我们将讨论指针与多维数组的关系。开始之前,让我们回顾一下什么是多维数组。
1. 声明数组
数组是由一系列类型相同的数据对象依次排列组成的复合结构。那么声明数组时至少要提供三类参数:
1. 数组名。
2. 数组元素的类型。
3. 数组元素的数量。
数组声明的公式为:
```
类型 数组名[元素数量];
```
例如,一个数组 A,它的元素为 `int` 类型,元素数量为10个。
1. 数组名:A
2. 数组元素的类型:int
3. 数组元素的数量:10
数组 A 的声明如下:
```
int A[10];
```
假设另一个数组 B,它的元素类型为数组 `int[10]`,元素数量为5个。
1. 数组名:B
2. 数组元素的类型:int[10]
3. 数组元素的数量:5
数组 B 的声明如下:
```
int B[5][10];
```
访问数组 A 的元素需要一个下标,例如 `A[x]`。而访问数组 B 的元素需要两个下标,例如 `B[x][y]`。数组 A 为一维数组,而数组 B 为二维数组。
2. 数组名的转换规则
数组名出现在表达式中时,将被转换为指向数组首元素的指针。但有两个例外:
1. 对数组名使用 `sizeof` 时。
2. 对数组名使用 `&` 时。
3. 多维数组名与指针
通过实际示例探讨指针与多维数组的关系:
```
#include <stdio.h>
int main()
{
int A[10];
int B[5][10];
printf("sizeof A = %lu\n", sizeof(A));
printf("sizeof B = %lu\n", sizeof(B));
return 0;
}
```
在上面的代码中,A 的类型为 `int[10]`,B 的类型为 `int[5][10]`。
A 的空间大小为 `sizeof(int) * 10 = 40`。
B 的空间大小为 `sizeof(int[10]) * 5 = 200`。
接下来探讨数组名被转换的情况:
```
#include <stdio.h>
int main()
{
int A[10];
int B[5][10];
int *pA;
int (*pB)[10];
pA = A;
pB = B;
return 0;
}
```
在上面的代码中,数组名 A 将被转换为指向数组首元素的指针类型 `int *`,数组名 B 将被转换为指向数组首元素的指针类型 `int (*)[10]`。
```
#include <stdio.h>
int main()
{
int B[5][10] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
{20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
{30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
{40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
};
int (*pInt10)[10] = B;
printf("pInt10 = %p\n", pInt10);
printf("pInt10 + 1 = %p\n", pInt10 + 1);
printf("pInt10 + 2 = %p\n", pInt10 + 2);
return 0;
}
```
在上面的代码中,指针 `pInt10` 被初始化为指向数组 B 的首元素,即类型转换为 `int (*)[10]`。我们可以通过移动指针访问不同数组:
```
#include <stdio.h>
int main()
{
int B[5][10] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
{20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
{30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
{40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
};
int (*pInt10)[10] = B;
int *pInt = *pInt10;
printf("pInt[0] = %d\n", pInt[0]);
printf("pInt[1] = %d\n", pInt[1]);
printf("pInt[2] = %d\n", pInt[2]);
return 0;
}
```
在这个例子中,`pInt10` 先从 `int (*)[10]` 转换为 `int [10]`,然后从 `int [10]` 转换为 `int *`。通过 `pInt10` 可以遍历整个二维数组的元素。
4. 指针与数组名互换访问
任何数组在内存中都是连续的,二维数组也不例外:
```
#include <stdio.h>
int main()
{
int B[5][10] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
{20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
{30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
{40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
};
int *pInt = B[0];
printf("pInt[0] = %d\n", pInt[0]);
printf("pInt[1] = %d\n", pInt[1]);
printf("pInt[2] = %d\n", pInt[2]);
printf("pInt[10] = %d\n", pInt[10]);
return 0;
}
```
5. 对数组取地址
当对数组名使用 `&`,不会进行类型转换。例如,对于 `int arr[10];`,`&arr` 的类型为 `int (*)[10]`:
```
#include <stdio.h>
int main()
{
int arr[10];
int (*pInt10)[10] = &arr;
printf("pInt10 = %p\n", pInt10);
printf("pInt10 + 1 = %p\n", pInt10 + 1);
return 0;
}
```
通过这种方法,我们可以正确地使用指针指向数组并操作数组的数据。
通过这些示例,我们可以更加清晰地理解指针与多维数组的关系,并且可以灵活地对多维数组进行遍历和操作。