C语言指针与数组 #
一、数组名与指针 #
1.1 数组名的本质 #
数组名是数组首元素的地址:
c
int arr[5] = {1, 2, 3, 4, 5};
arr 等价于 &arr[0]。
c
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
printf("arr = %p\n", (void*)arr);
printf("&arr[0] = %p\n", (void*)&arr[0]);
printf("*arr = %d\n", *arr);
return 0;
}
1.2 数组名与指针的区别 #
c
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int* p = arr;
printf("sizeof(arr) = %zu\n", sizeof(arr));
printf("sizeof(p) = %zu\n", sizeof(p));
return 0;
}
输出:
text
sizeof(arr) = 20
sizeof(p) = 8
区别:
| 特性 | 数组名 | 指针 |
|---|---|---|
| 本质 | 地址常量 | 变量 |
| sizeof | 整个数组大小 | 指针大小 |
| 可修改 | 否 | 是 |
1.3 &arr 与 arr #
c
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
printf("arr = %p\n", (void*)arr);
printf("arr+1 = %p\n", (void*)(arr+1));
printf("&arr = %p\n", (void*)&arr);
printf("&arr+1 = %p\n", (void*)(&arr+1));
return 0;
}
输出:
text
arr = 0x7fff5fbff8a0
arr+1 = 0x7fff5fbff8a4
&arr = 0x7fff5fbff8a0
&arr+1 = 0x7fff5fbff8b4
arr类型是int*,+1 偏移4字节&arr类型是int(*)[5],+1 偏移20字节
二、指针遍历数组 #
2.1 基本遍历 #
c
#include <stdio.h>
int main() {
int arr[5] = {10, 20, 30, 40, 50};
int* p = arr;
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, *(p + i));
}
return 0;
}
2.2 指针自增遍历 #
c
#include <stdio.h>
int main() {
int arr[5] = {10, 20, 30, 40, 50};
int* p = arr;
for (int i = 0; i < 5; i++) {
printf("%d ", *p++);
}
printf("\n");
return 0;
}
2.3 指针范围遍历 #
c
#include <stdio.h>
int main() {
int arr[5] = {10, 20, 30, 40, 50};
int* start = arr;
int* end = arr + 5;
for (int* p = start; p < end; p++) {
printf("%d ", *p);
}
printf("\n");
return 0;
}
2.4 修改数组元素 #
c
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int* p = arr;
for (int i = 0; i < 5; i++) {
*p *= 2;
p++;
}
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
输出:
text
2 4 6 8 10
三、数组作为函数参数 #
3.1 数组退化为指针 #
c
#include <stdio.h>
void print_array(int arr[], int size) {
printf("sizeof(arr) = %zu\n", sizeof(arr));
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
printf("sizeof(arr) = %zu\n", sizeof(arr));
print_array(arr, 5);
return 0;
}
输出:
text
sizeof(arr) = 20
sizeof(arr) = 8
数组作为参数时退化为指针。
3.2 等价写法 #
c
void func(int arr[]);
void func(int* arr);
两种写法等价。
3.3 传递数组大小 #
c
#include <stdio.h>
int sum(int* arr, int size) {
int total = 0;
for (int i = 0; i < size; i++) {
total += arr[i];
}
return total;
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
int size = sizeof(arr) / sizeof(arr[0]);
printf("总和: %d\n", sum(arr, size));
return 0;
}
3.4 使用指针参数 #
c
#include <stdio.h>
void double_values(int* start, int* end) {
while (start < end) {
*start *= 2;
start++;
}
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
int size = sizeof(arr) / sizeof(arr[0]);
double_values(arr, arr + size);
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
四、指针数组 #
4.1 定义 #
指针数组是元素为指针的数组:
c
int* arr[5];
这是一个包含5个 int* 元素的数组。
4.2 使用示例 #
c
#include <stdio.h>
int main() {
int a = 10, b = 20, c = 30;
int* arr[3] = {&a, &b, &c};
for (int i = 0; i < 3; i++) {
printf("arr[%d] = %d\n", i, *arr[i]);
}
return 0;
}
4.3 字符串数组 #
c
#include <stdio.h>
int main() {
const char* names[] = {"Alice", "Bob", "Charlie", "David"};
int size = sizeof(names) / sizeof(names[0]);
for (int i = 0; i < size; i++) {
printf("names[%d] = %s\n", i, names[i]);
}
return 0;
}
五、数组指针 #
5.1 定义 #
数组指针是指向数组的指针:
c
int (*p)[5];
这是一个指向包含5个int元素数组的指针。
5.2 使用示例 #
c
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &arr;
for (int i = 0; i < 5; i++) {
printf("%d ", (*p)[i]);
}
printf("\n");
return 0;
}
5.3 指针数组 vs 数组指针 #
c
int* arr[5];
int (*p)[5];
| 类型 | 含义 |
|---|---|
| int* arr[5] | 包含5个int指针的数组 |
| int (*p)[5] | 指向包含5个int数组的指针 |
5.4 记忆方法 #
[]优先级高于*int* arr[5]:arr先与[]结合,是数组int (*p)[5]:p先与*结合,是指针
六、多维数组与指针 #
6.1 二维数组 #
c
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
6.2 理解二维数组 #
text
arr[i][j] 等价于 *(*(arr + i) + j)
c
#include <stdio.h>
int main() {
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
printf("arr = %p\n", (void*)arr);
printf("arr[0] = %p\n", (void*)arr[0]);
printf("&arr[0][0] = %p\n", (void*)&arr[0][0]);
printf("arr[1] = %p\n", (void*)arr[1]);
printf("arr[1] - arr[0] = %ld\n", arr[1] - arr[0]);
return 0;
}
6.3 指针遍历二维数组 #
c
#include <stdio.h>
int main() {
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int* p = &arr[0][0];
int total = 3 * 4;
for (int i = 0; i < total; i++) {
printf("%d ", *p++);
}
printf("\n");
return 0;
}
6.4 行指针 #
c
#include <stdio.h>
int main() {
int arr[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int (*p)[4] = arr;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%2d ", p[i][j]);
}
printf("\n");
}
return 0;
}
七、实战应用 #
7.1 动态数组 #
c
#include <stdio.h>
#include <stdlib.h>
int main() {
int size = 5;
int* arr = (int*)malloc(size * sizeof(int));
if (arr == NULL) {
return 1;
}
for (int i = 0; i < size; i++) {
arr[i] = i + 1;
}
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
free(arr);
return 0;
}
7.2 字符串处理 #
c
#include <stdio.h>
int main() {
const char* fruits[] = {"Apple", "Banana", "Cherry"};
int size = sizeof(fruits) / sizeof(fruits[0]);
for (int i = 0; i < size; i++) {
printf("%s\n", fruits[i]);
}
return 0;
}
7.3 矩阵操作 #
c
#include <stdio.h>
void print_matrix(int (*mat)[4], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 4; j++) {
printf("%2d ", mat[i][j]);
}
printf("\n");
}
}
int main() {
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
print_matrix(matrix, 3);
return 0;
}
八、总结 #
数组名与指针 #
| 概念 | 说明 |
|---|---|
| arr | 首元素地址 |
| &arr | 整个数组地址 |
| arr[i] | *(arr + i) |
| &arr[i] | arr + i |
指针数组 vs 数组指针 #
| 类型 | 定义 | 用途 |
|---|---|---|
| 指针数组 | int* arr[5] | 存储多个指针 |
| 数组指针 | int (*p)[5] | 指向数组 |
多维数组 #
c
arr[i][j] ≡ *(*(arr + i) + j)
函数参数 #
数组作为参数退化为指针,需要传递大小。
下一步,让我们学习指针与函数!
最后更新:2026-03-26