017. 理解指针与数组的关系
在C语言中,指针和数组之间有着非常紧密的关系。理解它们之间的关系对于掌握C语言的高级特性非常重要。以下将详细解释指针与数组的关系,并通过具体示例帮助你更好地理解。
1. 数组的本质
在C语言中,数组本质上是一块连续的内存区域,用于存储多个相同类型的元素。数组的名称实际上是一个指向数组首元素的指针。
示例代码
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5}; // 声明并初始化一个数组
int *ptr = arr; // 将指针初始化为数组的首地址
printf("Address of arr: %p\n", arr); // 输出数组的首地址
printf("Address of arr[0]: %p\n", &arr[0]); // 输出数组第一个元素的地址
printf("Address stored in ptr: %p\n", ptr); // 输出指针存储的地址
return 0;
}
输出结果
Address of arr: 0x7ffd5b9a5a44
Address of arr[0]: 0x7ffd5b9a5a44
Address stored in ptr: 0x7ffd5b9a5a44
解释
-
arr
是数组的名称,它表示数组的首地址。 -
&arr[0]
是数组第一个元素的地址。 -
ptr
是一个指针,初始化为数组的首地址。 -
从输出结果可以看出,
arr
、&arr[0]
和ptr
都指向同一个地址。
2. 通过指针访问数组元素
可以使用指针来访问数组的元素。通过指针加偏移量的方式,可以访问数组中的任意元素。
示例代码
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5}; // 声明并初始化一个数组
int *ptr = arr; // 将指针初始化为数组的首地址
printf("Element at index 0: %d\n", *ptr); // 通过指针访问第一个元素
printf("Element at index 1: %d\n", *(ptr + 1)); // 通过指针访问第二个元素
printf("Element at index 2: %d\n", *(ptr + 2)); // 通过指针访问第三个元素
return 0;
}
输出结果
Element at index 0: 1
Element at index 1: 2
Element at index 2: 3
解释
-
*ptr
表示指针所指向的值,即数组的第一个元素。 -
*(ptr + 1)
表示指针加1后所指向的值,即数组的第二个元素。 -
*(ptr + 2)
表示指针加2后所指向的值,即数组的第三个元素。
3. 数组名作为函数参数
当数组作为函数参数时,传递的是数组的首地址。因此,函数内部可以通过指针操作来访问和修改数组的元素。
示例代码
#include <stdio.h>
// 函数定义:通过指针修改数组元素
void incrementArray(int *arr, int size) {
for (int i = 0; i < size; i++) {
arr[i]++; // 通过指针修改数组元素
}
}
int main() {
int arr[] = {1, 2, 3, 4, 5}; // 声明并初始化一个数组
int size = sizeof(arr) / sizeof(arr[0]); // 计算数组的大小
printf("Before incrementing:\n");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 调用函数并传递数组
incrementArray(arr, size);
printf("After incrementing:\n");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
输出结果
Before incrementing:
1 2 3 4 5
After incrementing:
2 3 4 5 6
解释
-
在
incrementArray
函数中,arr
是一个指向数组首地址的指针。 -
通过
arr[i]
可以访问和修改数组的元素。
4. 指针与数组的等价性
在大多数情况下,数组名可以被看作是指向数组首元素的指针。以下是一些等价的表达式:
-
arr[i]
等价于*(arr + i)
-
&arr[i]
等价于arr + i
示例代码
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3, 4, 5}; // 声明并初始化一个数组
printf("Element at index 2 (arr[2]): %d\n", arr[2]); // 通过数组访问
printf("Element at index 2 (*(arr + 2)): %d\n", *(arr + 2)); // 通过指针访问
printf("Address of element at index 2 (&arr[2]): %p\n", &arr[2]); // 通过数组获取地址
printf("Address of element at index 2 (arr + 2): %p\n", arr + 2); // 通过指针获取地址
return 0;
}
输出结果
Element at index 2 (arr[2]): 3
Element at index 2 (*(arr + 2)): 3
Address of element at index 2 (&arr[2]): 0x7ffd5b9a5a50
Address of element at index 2 (arr + 2): 0x7ffd5b9a5a50
5. 二维数组与指针
对于二维数组,数组名是一个指向数组第一行的指针。可以通过指针操作来访问和修改二维数组的元素。
示例代码
#include <stdio.h>
int main() {
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
}; // 声明并初始化一个二维数组
int (*ptr)[4] = matrix; // 声明一个指向二维数组的指针
printf("Element at [1][2] (matrix[1][2]): %d\n", matrix[1][2]); // 通过数组访问
printf("Element at [1][2] (*(*(ptr + 1) + 2)): %d\n", *(*(ptr + 1) + 2)); // 通过指针访问
return 0;
}
输出结果
Element at [1][2] (matrix[1][2]): 7
Element at [1][2] (*(*(ptr + 1) + 2)): 7
解释
-
matrix
是一个二维数组的名称,它是一个指向数组第一行的指针。 -
ptr
是一个指向二维数组的指针,可以通过*(*(ptr + 1) + 2)
来访问二维数组的元素。
通过上述示例,你可以看到指针与数组之间的紧密关系:
- 数组名是一个指针:数组名表示数组的首地址。
- 通过指针访问数组元素:可以使用指针加偏移量的方式访问数组元素。
- 数组作为函数参数:传递的是数组的首地址,函数内部可以通过指针操作数组。
- 指针与数组的等价性:
arr[i]
等价于*(arr + i)
,&arr[i]
等价于arr + i
。 - 二维数组与指针:二维数组的名称是一个指向数组第一行的指针。
视频讲解
BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)