数组名作为指针常量的核心概念
在C/C++中,数组名在大多数情况下会被自动转换为指向数组首元素的指针。例如定义整型数组:
int a[5] = {10, 20, 30, 40, 50};
此时a
等价于&a[0]
,类型为int*
。
元素访问的等价形式
值访问:
a[i] // 数组下标形式
*(a + i) // 指针解引用形式
地址获取:
&a[i] // 取地址符形式
a + i // 指针运算形式
指针变量操作数组
定义指针变量:
int* p = a; // p指向数组首地址
访问元素的三种方式:
p[i] // 指针下标形式
*(p + i) // 指针运算形式
a[i] // 原数组形式
灵活性对比:
p++; // 合法(指向下一元素)
a++; // 非法(数组名是常量)
指针运算原理
指针加减整数时,实际偏移量根据类型自动计算:
p + 2 // 实际移动 2 * sizeof(int) 字节
假设int
占4字节,p + 2
将移动8字节。
关键特性对比
特性 | 数组名a | 指针变量p |
---|---|---|
可变性 | 不可变(常量) | 可变 |
自增操作 | a++ 非法 | p++ 合法 |
内存占用 | 整个数组空间 | 指针空间 |
实际应用示例
遍历数组:
for (int* ptr = a; ptr < a + 5; ptr++) {
printf("%d ", *ptr); // 输出:10 20 30 40 50
}
函数参数传递:
void printArray(int* arr, int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]); // 等价于*(arr + i)
}
}
常见误区图解
内存布局:
┌─────┬─────┬─────┬─────┬─────┐
│ a[0]│ a[1]│ a[2]│ a[3]│ a[4]│
└─────┴─────┴─────┴─────┴─────┘
↑ ↑ ↑
a a+1 a+2
关键区别:
a
→ 指向首元素(int*
)&a
→ 指向整个数组(int(*)[5]
&a+1
是基于&a
的指针运算。由于&a
是指向整个数组的指针,+1
会跨越整个数组的大小。- 对于
int a[5]
,&a+1
的地址是&a
加上sizeof(int) * 5
字节,即跳过整个数组,指向数组末尾之后的位置(如下图所示)。
多维数组注意:
int b[3][4]; // b的类型是 int(*)[4],不是 int**
等价关系总结
数组形式 | 指针形式 |
---|---|
a[2] | *(a + 2) |
&a[2] | a + 2 |
掌握这些底层原理可提升数组操作的灵活性,并为动态内存分配等高级特性奠定基础。
数组名作为指针常量的核心概念
在C/C++中,数组名在大多数情况下会被自动转换为指向数组首元素的指针。例如定义整型数组:
int a[5] = {10, 20, 30, 40, 50};
此时a
等价于&a[0]
,类型为int*
。
元素访问的等价形式
值访问:
a[i] // 数组下标形式
*(a + i) // 指针解引用形式
地址获取:
&a[i] // 取地址符形式
a + i // 指针运算形式
指针变量操作数组
定义指针变量:
int* p = a; // p指向数组首地址
访问元素的三种方式:
p[i] // 指针下标形式
*(p + i) // 指针运算形式
a[i] // 原数组形式
灵活性对比:
p++; // 合法(指向下一元素)
a++; // 非法(数组名是常量)
指针运算原理
指针加减整数时,实际偏移量根据类型自动计算:
p + 2 // 实际移动 2 * sizeof(int) 字节
假设int
占4字节,p + 2
将移动8字节。
关键特性对比
特性 | 数组名a | 指针变量p |
---|---|---|
可变性 | 不可变(常量) | 可变 |
自增操作 | a++ 非法 | p++ 合法 |
内存占用 | 整个数组空间 | 指针空间 |
实际应用示例
遍历数组:
for (int* ptr = a; ptr < a + 5; ptr++) {
printf("%d ", *ptr); // 输出:10 20 30 40 50
}
函数参数传递:
void printArray(int* arr, int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]); // 等价于*(arr + i)
}
}
常见误区图解
内存布局:
┌─────┬─────┬─────┬─────┬─────┐
│ a[0]│ a[1]│ a[2]│ a[3]│ a[4]│
└─────┴─────┴─────┴─────┴─────┘
↑ ↑ ↑
a a+1 a+2
关键区别:
a
→ 指向首元素(int*
)&a
→ 指向整个数组(int(*)[5]
)
多维数组注意:
int b[3][4]; // b的类型是 int(*)[4],不是 int**
等价关系总结
数组形式 | 指针形式 |
---|---|
a[2] | *(a + 2) |
&a[2] | a + 2 |
掌握这些底层原理可提升数组操作的灵活性,并为动态内存分配等高级特性奠定基础。