C语言指针与数组:到底有什么区别
2026/8/24大约 2 分钟
C语言指针与数组:到底有什么区别
一、本质不同
数组:
int arr[5] = {1, 2, 3, 4, 5};表示:
一块连续的内存空间。
指针:
int *p = arr;表示:
一个保存地址的变量。
可以理解成:
arr
↓
┌───┬───┬───┬───┬───┐
│ 1 │ 2 │ 3 │ 4 │ 5 │
└───┴───┴───┴───┴───┘
p ─────────→ arr[0]二、为什么 arr 不能 ++,而 p 可以?
int arr[5];
int *p = arr;指针是变量:
p++;可以:
p → arr[0]
p++
↓
p → arr[1]但:
arr++;错误。
因为:
数组名不是一个可以被重新赋值的指针变量。
数组 arr 代表的是这一整块数组对象:
arr
↓
固定的数组首地址它没有一个可以让你修改的“地址变量”。
所以:
arr = p; // ❌
arr++; // ❌
arr += 1; // ❌而:
p = p + 1; // ✅
p++; // ✅核心区别:
p是变量,可以改变它保存的地址;arr是数组对象,不能修改它的首地址。
三、但为什么 arr + 1 又可以?
因为在大多数表达式中:
arr会自动退化成:
&arr[0]所以:
arr + 1是合法的,表示:
arr[0]
↓
arr[1]因此:
*(arr + 1)等价于:
arr[1]注意:
可以用
arr + 1,但不能修改arr本身。
四、sizeof 完全不同
int arr[5];
int *p = arr;如果 int = 4 字节:
sizeof(arr); // 20
sizeof(p); // 4(32位环境)因为:
sizeof(arr)
→ 整个数组
sizeof(p)
→ 指针变量本身所以数组传进函数后经常出现:
void func(int arr[])
{
printf("%zu", sizeof(arr));
}这里的 arr 实际已经是:
int *所以拿不到整个数组大小。
五、函数传参:数组会退化成指针
void func(int *p);
int arr[5];
func(arr);传入 arr 后,本质上是:
func(&arr[0]);所以:
void func(int arr[])和:
void func(int *arr)在函数参数中基本等价。
因此数组长度需要单独传:
void func(int *arr, int len);六、arr 和 &arr 不是一回事
int arr[5];通常:
arr退化成:
int *指向第一个元素。
而:
&arr是:
int (*)[5]指向整个数组。
所以:
arr + 1移动一个 int。
而:
&arr + 1移动整个 int[5]。
七、最容易考的对比
int arr[5];
int *p = arr;| 操作 | arr | p |
|---|---|---|
arr + 1 | ✅ | ✅ |
arr++ | ❌ | ✅ |
arr = p | ❌ | ✅ |
sizeof | 整个数组 | 指针大小 |
| 本质 | 数组对象 | 地址变量 |
一句话记忆
数组提供一块固定的连续空间,指针保存一个可以改变的地址。
所以:
arr + 1 ✅ 可以计算
arr++ ❌ 不能修改数组名
p + 1 ✅ 可以计算
p++ ✅ 可以修改指针这就是数组和指针最核心的区别。

