news 2025/12/23 7:17:06

数组退化成指针的几种情况

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数组退化成指针的几种情况

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

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

二.举例

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]
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/17 0:17:19

关于VM的使用

1. VM功能介绍&#xff08;1&#xff09;功能一&#xff1a;挂起操作&#xff08;将操作暂时保存起来&#xff0c;方便下次接着使用&#xff09;&#xff08;2&#xff09;功能二&#xff1a;快照操作&#xff08;将操作保存起来&#xff0c;防止操作不当&#xff0c;可以回退到…

作者头像 李华
网站建设 2025/12/17 0:16:59

3分钟搞定!文泉驿微米黑字体全平台安装终极指南

3分钟搞定&#xff01;文泉驿微米黑字体全平台安装终极指南 【免费下载链接】fonts-wqy-microhei Debian package for WenQuanYi Micro Hei (mirror of https://anonscm.debian.org/git/pkg-fonts/fonts-wqy-microhei.git) 项目地址: https://gitcode.com/gh_mirrors/fo/font…

作者头像 李华
网站建设 2025/12/17 0:15:52

Flutter 状态管理全家桶:Provider、Bloc、GetX 实战对比

Flutter 状态管理全家桶&#xff1a;Provider、Bloc、GetX 实战对比 在 Flutter 开发中&#xff0c;状态管理是贯穿项目全生命周期的核心议题。从简单的按钮点击状态切换&#xff0c;到复杂的跨页面数据共享与业务逻辑联动&#xff0c;选择合适的状态管理方案直接决定了项目的…

作者头像 李华
网站建设 2025/12/17 0:15:45

Flutter 网络请求完全指南:Dio 封装与拦截器实战

Flutter 网络请求完全指南&#xff1a;Dio 封装与拦截器实战 在 Flutter 开发中&#xff0c;网络请求是连接前端与后端服务的核心桥梁&#xff0c;直接影响应用的交互体验与数据流转效率。Dio 作为 Flutter 生态中最主流的网络请求库&#xff0c;支持 RESTful API、FormData、…

作者头像 李华
网站建设 2025/12/17 0:15:14

DPO微调

&#x1f34b;&#x1f34b;AI学习&#x1f34b;&#x1f34b;&#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主…

作者头像 李华
网站建设 2025/12/19 15:56:05

内容管理系统(CMS)的7个关键特点

一套高效的内容管理系统&#xff08;CMS&#xff09;能帮你节省时间、开辟内容个性化的空间&#xff0c;并提升在线形象——从而改善业务成效。合适的CMS可以保持数字形象井然有序、品牌风格统一&#xff0c;并让内容流程顺畅运转&#xff0c;有助于在营销各个环节吸引并留住潜…

作者头像 李华