当前位置: 首页 > news >正文

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

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

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

二.举例

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]
http://www.cnnetsun.cn/news/94332.html

相关文章:

  • 字符设备驱动(5)
  • Flutter 表单开发实战:表单验证、输入格式化与提交处理
  • 【光子 AI】AI Agent 架构师 / 技术专家 10 道必考面试题和必过答案完整讲解 1
  • Flutter 主题与深色模式:全局样式统一与动态切换
  • 基于 GEE 使用 Sentinel-2 遥感影像数据反演水体叶绿素 a 质量浓度
  • 小红书数据采集架构解析与工程实践
  • 长沙对非合作深化 探索新型易货贸易
  • OpenCore Legacy Patcher终极教程:让老旧Mac完美运行最新macOS
  • 1、开启GIMP图像编辑之旅:从安装到精通
  • 2、开启 GIMP 图形编辑之旅
  • 怎么建立一套高效的设备运维管理体系?
  • 小爱音箱AI升级:让你的智能音箱秒变高智商语音助手
  • UnrealPakViewer终极指南:从入门到精通的Pak文件分析完整教程
  • 俄罗斯T-Tech公司推出T-pro 2.0:让AI说俄语更流利混合智能模型
  • MCP智能体连接协议面临企业级挑战
  • 联想发布数据存储新品助力企业AI发展
  • 人工智能使用大揭秘:OpenRouter公司百万亿规模数据分析报告
  • 微信DAT文件转换神器,牛批了
  • OBS音频插件实用技巧:专业级直播音效快速配置指南
  • BetterNCM插件配置全攻略:5步打造你的专属音乐工作站
  • 如何5分钟掌握网盘下载加速:告别限速的终极方案
  • 26年找实习的前端,建议跟着飞书准备面试...
  • 毕业论文知网AIGC怎么降?推荐10款免费降AI工具,完美保留原格式且无AI味!
  • “草台班子”的真相:为什么说未来十年,普通人逆袭的机会在这里?
  • 知网/维普AIGC怎么降?2025年降AI率工具大盘点,AI率低于10%且完美保留原格式!
  • 2025年降AI率哪个工具靠谱?5个工具核心优势解析,笔灵降AI性价比领先!
  • 年终总结,爆梗朋友圈
  • springboot健康管理小程序
  • PDF对比终极方案:如何用diff-pdf快速找出文档差异
  • Burp Suite抓包失败的5个常见原因及解决方法,第3个最容易被忽略!