数组退化成指针的几种情况
2026/8/29 19:43:43 网站建设 项目流程

一.什么是“数组退化成指针”?

在许多情况下,数组名会退化为指针,即原本代表数组的变量,变成了指向数组第一个元素的指针。这意味着数组名并不总是一个指向整个数组的指针,而是指向数组第一个元素的指针

二.举例

1.作为函数参数传递时

在函数参数中,数组总是退化为指针。这是因为函数参数的大小是固定的,而数组的大小在编译时并不确定。

#include <stdio.h> void foo(int arr[]) { printf("%zu\n", sizeof(arr)); // 输出指针的大小(4 或 8 字节) } int main() { int arr[10]; foo(arr); }

结果:sizeof(arr) 输出的是 指针的大小(4 或 8 字节,取决于32/64位平台)

分析:传递数组时,arr退化为指针sizeof(arr)返回的是指针的大小,而不是数组的大小。

void foo(int arr[ ]) 等价于void foo(int *arr)

2.作为函数参数的引用时

即使你使用引用(C++ 中)或者指针(C / C++ 中)传递数组,数组名依然会退化成指针。

#include <iostream> void foo(int* arr) { std::cout << sizeof(arr) << std::endl; // 输出指针大小 } int main() { int arr[10]; foo(arr); // 数组退化为指针 }

分析:arr作为参数传递给foo时,退化为指针,即传递给函数的是指向arr[0]的指针。

foo(arr)等价于foo(&a[0]);

3.用作sizeof表达式时

sizeof返回的是数组类型的大小,然而如果在数组名后加上 0,它会退化为指针类型,只看指针类型的大小。

#include <stdio.h> int main() { int arr[10]; printf("%zu\n", sizeof(arr)); // 数组的大小(40字节,假设 int 为4字节) printf("%zu\n", sizeof(arr+0)); // 指针的大小(4 或 8 字节) }

分析:

  • arr:在sizeof(arr)中,arr是一个数组,返回的是数组的总大小10 * sizeof(int))。

  • arr+0:在sizeof(arr+0)中,arr退化为指针(int*),sizeof返回的是指针的大小

4.在指针运算中

数组名在指针运算中始终退化为指针,因为数组名本质上是指向数组第一个元素的指针。

#include <stdio.h> int main() { int arr[5] = {1, 2, 3, 4, 5}; int *ptr = arr; // 数组退化为指针 printf("%d\n", *(ptr + 2)); // 输出 arr[2] 的值 3 }

分析:

  • arr被赋值给ptr,实际上是指针赋值,这时候arr退化为指向arr[0]的指针。

  • *(ptr + 2)实际上等价于arr[2]

5.作为函数返回值时(C++)

在 C++ 中,数组返回值也会退化为指针。如果你尝试返回整个数组,编译器会报错,但返回一个指向数组的指针是合法的。

#include <iostream> int* foo() { static int arr[3] = {1, 2, 3}; return arr; // 返回指向数组的指针 } int main() { int* ptr = foo(); std::cout << ptr[1] << std::endl; // 输出 2 }

分析:

  • 由于arr是一个局部数组,返回其指针是合法的(arr退化为指向arr[0]的指针)。

  • 注意:数组名退化为指针,因此你得到的是指向数组首元素的指针。

6.数组作为运算中的操作数时

在许多情况下,数组名也会自动退化为指针,尤其是作为运算的操作数时。

#include <stdio.h> int main() { int arr[3] = {1, 2, 3}; printf("%d\n", *(arr + 1)); // 输出 2 }

分析:

  • 这里arr退化为指向arr[0]的指针,arr + 1就是指向arr[1]的指针,*(arr + 1)解引用它,得到 2。

三、总结 & 避免数组传参退化的方法

数组在传参时默认会退化为指向首元素的指针,但这是由形参类型决定的,如果形参不是“数组引用”或“指向数组的指针”,则实参数组一定会发生数组到指针的转换也就是所谓的退化

简单说:只有当形参显式表示“整个数组类型”时,退化才不会发生。

那什么是形参为“数组引用”或“指向数组的指针”??

1.指向数组的指针(C / C++)

void foo(int (*arr)[10]);
int a[10]; foo(&a);
  • 实参传的是&a,类型匹配int (*)[10],没有退化

2.数组引用(C++)

void foo(int (&arr)[10]);
int a[10]; foo(a);
  • arr是数组引用,数组身份被完整保留没有退化

情况是否退化
foo(arr)✅ 实参处发生转换
void foo(int arr[])
void foo(int *arr)
void foo(int (*arr)[N])
void foo(int (&arr)[N])
sizeof(arr)
&arr

数组名在函数调用中作为形参时,普通写法一定会退化,只有参数代表整个数组类型,它才能接收整个数组否则都是接收的单个元素,正确不退化的形参写法:void foo( int (* arr )[10] )

写法指向
int *p单个 int
int (*p)[10]整个 int[10]

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询