数组名在c++++中不是指针变量,但在多数表达式中会自动转换为指向首元素的指针。1. 数组名本质是数组类型,不可赋值,类似int* const但并非真正指针;2. 作为左值可取地址但不可修改;3. 传参时退化为指针,导致sizeof失效;4. &arr表示整个数组地址,与arr类型不同;5. 使用引用可保留数组大小信息。掌握这些规则有助于更安全高效地使用数组。

数组名在C++中常被理解为一个指针常量,这个说法虽然不是完全准确,但确实能帮助我们更好地理解它的一些行为。简单来说,数组名在大多数情况下会自动转换为指向其第一个元素的指针,但它本身并不是一个变量,而是一个具有地址意义的常量。

数组名的本质:不是指针,但像指针
很多人第一次听说“数组名是常量指针”时会觉得有点抽象。其实这主要体现在它的使用方式上:

- 当你写
int arr[5];时,arr是一个数组类型,而不是指针。 - 但在表达式中(比如赋值、传参),除了少数几种情况(如
sizeof(arr)或&arr),arr会被自动转换为指向首元素的指针,即&arr[0]。 - 这个指针是不能被修改的,也就是说你不能写
arr = something;,因为数组名不是一个变量。
所以你可以把它想象成类似 int* const 的东西,但它本质上不是一个真正的指针变量。
立即学习“C++免费学习笔记(深入)”;
左值与右值特性分析
数组名在表达式中的表现还涉及左值和右值的问题:

- 数组名是一个左值,因为它表示的是内存中一块连续空间的起始位置。
- 但它不能作为可修改的左值,因为你不能对它进行赋值或者改变它的地址。
举个例子:
int arr[10]; int *p = arr; // 合法,arr 被当作地址使用 arr = p; // 不合法!arr 不能被赋值
这种限制来源于数组名代表的是一个固定地址,无法重新绑定到另一个内存块。
左值特性总结:
- 可取地址
- 表示对象身份
- 但不可赋值(不是可变左值)
右值一般指的是临时值,而数组名不是临时值,因此它不属于右值。
数组名在函数参数传递中的表现
当你把数组作为参数传入函数时,数组名会退化为指针:
void func(int arr[]) {
// 实际上等价于 int *arr
}这时候你传进去的只是一个指针,而不是整个数组。这也是为什么你在函数内部无法通过 sizeof(arr) 得到数组长度的原因。
所以,如果你希望保留数组大小信息,可以这样写:
void func(int (&arr)[5]) { /* 必须传入大小为5的数组 */ }这种方式利用了引用,避免了数组退化为指针的问题。
几个容易混淆的点
-
&arr和arr的区别-
arr在表达式中通常表示&arr[0],即指向第一个元素的指针。 -
&arr是整个数组的地址,类型是int(*)[5],和普通指针类型不同。
-
-
sizeof(arr)的结果- 如果
arr是真正的数组名,在函数外使用sizeof(arr)会返回整个数组占用的字节数。 - 但如果
arr是函数参数里的数组名(已经退化为指针),那sizeof(arr)返回的就是指针的大小(通常是4或8字节)。
- 如果
-
arr + 1的含义-
arr看作指针的话,加1就是跳过一个元素的大小。 - 如果用
(&arr) + 1,则是跳过整个数组的空间。
-
基本上就这些。数组名看似是个指针,实则有它的特殊规则,尤其是在左值、右值、函数参数传递等方面。掌握这些细节,有助于写出更安全、高效的代码。










