C_数组_数组与指针关系
数组对象和首元素很多人学习 C 语言时都会听过一句话数组就是指针。也有人说数组名就是一个指针。甚至有人说数组和指针完全一样。答案是否定的。数组不是指针。指针也不是数组。这是从 C89 到 C23 都没有改变的核心规则。在这个表达式中数组名arr发生了数组退化转换成了指向数组的首元素的指针因此它的值与arr[0]相同。arrarr[0]首元素指针地址1000数组对象本身没有发生任何改变。数组对象↓数组名 arr↓在普通表达式中发生转换↓arr[0]↓首元素地址1000所以,arr不是第一个元素。它只是在需要指针值的场景下转换成首元素指针地址1000。数组退化:arrarr[0]首元素指针地址为什么叫“退化”其实很好理解。数组原本拥有自己完整类型。例如int arr[5];它的类型是int[5] 表示 一个包含 5 个 int 元素的数组对象。但是在很多表达式中C 语言会把数组名arr转换成int * 指针类型,指向第一个元素的指针1000 。这就叫数组退化数组退化后: int *p arrarr[0]首元素指针地址1000int *p arr; 等价于int *p arr[0];数组退化过程数组对象arr┌────┬────┬────┬────┬────┐│ 10 │ 20 │ 30 │ 40 │ 50 │└────┴────┴────┴────┴────┘↓数组退化↓arr[0]↓int *↓数组退化后: int *p arrarr[0]首元素指针地址1000注意这里没有复制整个数组。没有创建新的内存。也没有把数组变成指针。只是数组名在当前表达式中产生了一个指向首元素的指针值。请记住一句非常重要的话数组对象不会退化发生退化的是数组名在表达式中的转换。为什么很多人会误以为数组就是指针int arr[5] { 10,20,30,40,50 }; int * p arr; printf(arr[0]%p\n, arr[0]); //arr[0]000000000000000A printf(p[0]%p\n, p[0]); //p[0]000000000000000A printf(arr[2]%p\n, arr[2]); //arr[2]000000000000001E printf(p[2]%p\n, p[2]); //p[2]000000000000001E printf(*(arr 3)%p\n, *(arr3)); //*(arr 3)0000000000000028 printf(*(p 3)%p\n, *(p3)); //*(p 3)0000000000000028通过以上案例,很多人认为 数组就是指针。其实真正正确的理解是数组退化以后得到的指针和普通指针具有相同的使用方式。数组本身依然不是指针。真正参与指针运算的是谁数组对象 arr┌────┬────┬────┬────┬────┐│ 10 20 30 40 50└────┴────┴────┴────┴────┘1000 1004 1008 1012 1016↓数组退化首元素地址 arr1000↓ 指针运算arr 1 1004arr 2 1008arr 3 1012真正参与arr 1 arr 2 arr 3 运算的并不是数组对象。而是 数组退化之后得到的指针参与运算。数组到底是什么数组是一块连续存放多个相同类型元素的内存空间。int arr[5];表示5 个连续的 int 元素.而不是一个指针变量.数组真正的结构┌────────┬────────┬────────┬────────┬────────┐│ int │ int │ int │ int │ int │└────────┴────────┴────────┴────────┴────────┘│ 10 │ 20 │ 30 │ 40 │ 50 │└────────┴────────┴────────┴────────┴────────┘数组对象 arr 一整块连续内存这里没有int *这样的指针变量。数组对象本身就是这块连续空间。例如int arr[5];创建数组arr的 地址1000┌────┬────┬────┬────┬────┐│ │ │ │ │ │└────┴────┴────┴────┴────┘1000 1004 1008 1012 1016而int *p arr;创建的是p┌────────┐│ 1000 │└────────┘也就是说arr是一整块连续内存p是保存地址的指针变量两者从本质上完全不同。本节小结到这里我们已经得到三个重要结论✅数组不是指针。✅数组对象是一块连续内存。✅数组名arr在大多数表达式中会转换成指向首元素的指针。为什么arr[i]等于*(arr i)很多人第一次看到arr[i] 等价于*(arr i)都会觉得不可思议。一个看起来像数组。一个看起来像指针。为什么它们完全一样其实这是 C 语言定义数组下标运算时的规则。C 标准规定E1[E2]等价于*((E1) (E2))也就是说arr[i] 等价于 *(arr i)arr[i] 等于*(arr i)推到过程:int arr[5] { 10,20,30,40,50 }数组名arr数组名arr数组名arr数组名arr数组名arr数组arr退化为 arr[0]数组arr退化为 arr[0]数组arr退化为 arr[0]数组arr退化为 arr[0]数组arr退化为arr[0]第一个元素的 指针运算0后内存地址: arr[0]0第二个元素的指针运算1后内存地址: arr[0]1第三个元素的指针运算2后内存地址: arr[0]2第四个元素 的指针运算3后内存地址: arr[0]3第五个元素的指针运算4后内存地址arr[0 ]4*解引用*(arr[0]0)10*解引用*(arr[0]1)20*解引用* (arr[0]2) 30*解引用* (arr[0]3) 40*解引用*(arr[0]4) 50数组退化后arrarr[0]数组退化后arrarr[0]数组退化后arrarr[0]数组退化后arrarr[0]数组退化后arrarr[0]简写*(arr[0]0)*(arr0)10arr[0]简写*(arr[0]1)*(arr1)20arr[1]简写* (arr[0]2)*(arr2) 30arr[2]简写* (arr[0]3)*(arr3) 40arr[3]简写*(arr[0]4)*(arr4) 50arr[4]结论:arr[i] *(arr i)数据内容数组arr[0]*(arr 0)10arr[1]*(arr 1)20arr[2]*(arr 2)30arr[3]*(arr 3)40arr[4]*(arr 4)50数组下标操作本质上就是指针运算加解引用。数组下标操作本质上就是指针运算加解引用。所以:p[i]*(p i)元素值还有一个 C 语言经典冷知识a[b] *(ab)p[i]*(p i)推到过程:int arr[5] { 10,20,30,40,50 };int* p arr;因为 arr[i] *(arr i)所以 p[i]*(p i)p[0]*(p 0)10p[1]*(p 1)20p[2]*(p 2)30p[3]*(p 3)40p[4]*(p 4)50int arr[5] { 10,20,30,40,50 }; int* p arr; printf(p[0]%d\n, p[0]); //p[0]10 printf(*(p 0)%d\n, *(p 0));//*(p 0)10 printf(p[1]%d\n, p[1]);//p[1]20 printf(*(p 1)%d\n, *(p 1));//*(p 1)20 printf(p[2]%d\n, p[2]);//p[2]30 printf(*(p 2)%d\n, *(p 2));//*(p 2)30 printf(p[3]%d\n, p[3]); //p[3]40 printf(*(p 3)%d\n, *(p 3)); //*(p 3)40 printf(p[4]%d\n, p[4]); //p[4]50 printf(*(p 4)%d\n, *(p 4)); //*(p 4)50arr、arr和arr[0]到底有什么区别int arr[5] { 10,20,30,40,50 }; printf(arr%p\n, (void *)arr); //arr0000004DA8AFF5E8 printf(arr[0]%p\n, (void *)arr[0]); //arr[0]0000004DA8AFF5E8 printf(arr%p\n, (void *)arr); //arr0000004DA8AFF5E8通过以上案例 发现arr、arr和arr[0]的内存地址值都一样,很多人就认为 arrarr[0]arr 这是错误的认识。正确理解虽然它们的内存地址数值可能相同但类型和含义完全不同。arr单独使用arr在普通表达式中会发生数组退化。类型: int *表示指向第一个 int 元素的指针。arrarr[0]00000079070FF4D8arr[0]arr[0]更加直接。它就是第一个元素的内存地址。类型: int *所以arr 退化后arrarr[0]00000079070FF4D8arrarr表示指向的是整个数组对象的内存地址。类型int (*)[5]读作指向包含 5 个 int 元素数组的指针。注意它不是int *而是int (*)[5]为什么arr 1和arr 1完全不同arr 1arr 数组退化后: int * 类型指针 指向第一个元素的内存地址int *p arrarr[0]首元素指针地址00000036E47DF658(当前p指向第一个元素的内存地址)p指针移动一个元素。 移动一个 sizeof(int)4Byte字节意识就是p 指向第二个元素的内存地址 arr 1 int * 100000036E47DF65Cint arr[5] { 10,20,30,40,50 }; //首先arr 数组退化后: int * 类型指针 指向第一个元素的内存地址 // int *p arrarr[0]首元素指针地址00000036E47DF658 int* p arr; printf(p%p\n, p);//p第一个元素的内存地址00000036E47DF658 // (当前p指向第一个元素的内存地址)p指针移动一个元素。 移动一个 sizeof(int)4Byte字节 // 意识就是p 指向第二个元素的内存地址 arr 1 int * 100000036E47DF65C int* p1 arr1; printf(p1%p\n, p1); //p100000036E47DF65Carr 1arr 表示指向的是整个数组对象的内存地址000000814ACFFBA8。 类型int (*)[5]arr 1 移动单位不是一个sizeof(int)4字节。而是 把整个数组对象的内存地址000000814ACFFBA8 移动sizeof(arr)5*sizeof(int)20 Byte字节长度后的新的内存地址000000814ACFFBBC。int arr[5] { 10,20,30,40,50 }; //arr 表示指向的是整个数组对象的内存地址000000814ACFFBA8。 类型int (*)[5] //arr 1 移动单位不是一个sizeof(int)4字节。 // 而是 把整个数组对象的内存地址000000814ACFFBA8 // 移动sizeof(arr)5*sizeof(int)20 Byte字节长度后的新的内存地址000000814ACFFBBC。 printf(arr%p\n, (void*)arr);// arr 000000814ACFFBA8 printf(arr 1%p\n, arr 1);// arr 1 000000814ACFFBBC数组arr不退化成指针的场景前面一直说数组名arr在大多数表达式中会转换成指针。注意是大多数。不是全部。1. sizeof(arr)里的数组arr 不会退化AHHDHF HF HD HF

相关新闻

网络设备接入交换机后Ping不通?从物理到逻辑的完整排查指南

网络设备接入交换机后Ping不通?从物理到逻辑的完整排查指南

1. 问题现象与初步排查“设备接上交换机,灯也亮了,但就是ping不通。” 这几乎是每个网络工程师或IT运维在职业生涯中都会遇到的“经典开局”。它不像服务器宕机那样直接,也不像配置错误那样有明确指向,更像是一个需要你抽丝剥茧的…

2026/8/5 11:45:16 阅读更多 →
5分钟快速恢复QQ空间历史记录:GetQzonehistory终极指南

5分钟快速恢复QQ空间历史记录:GetQzonehistory终极指南

5分钟快速恢复QQ空间历史记录:GetQzonehistory终极指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否担心QQ空间里那些承载青春记忆的说说会随着时间流逝而消失&…

2026/8/5 11:44:16 阅读更多 →
终极泰拉瑞亚地图编辑器:10分钟从新手变造物主

终极泰拉瑞亚地图编辑器:10分钟从新手变造物主

终极泰拉瑞亚地图编辑器:10分钟从新手变造物主 【免费下载链接】Terraria-Map-Editor TEdit - Terraria Map Editor - TEdit is a stand alone, open source map editor for Terraria. It lets you edit maps just like (almost) paint! It also lets you change wo…

2026/8/5 11:44:16 阅读更多 →

最新新闻

UE4.27源码在Windows 10与VS2019环境下的编译实战与疑难排解

UE4.27源码在Windows 10与VS2019环境下的编译实战与疑难排解

1. 项目概述与核心价值如果你是一名使用虚幻引擎4(UE4)进行游戏开发或相关领域研发的从业者,那么从官方启动器下载预编译的引擎版本,可能是你接触UE4的第一步。然而,当你需要深度定制引擎功能、集成特定第三方库、或者…

2026/8/5 12:26:32 阅读更多 →
7步掌握Fillinger:让你的Illustrator设计效率提升300%

7步掌握Fillinger:让你的Illustrator设计效率提升300%

7步掌握Fillinger:让你的Illustrator设计效率提升300% 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts 你是否曾为了一张海报背景的装饰元素,手动复制粘贴上百…

2026/8/5 12:26:32 阅读更多 →
恶意代码分析实战:从PE结构、脱壳到API行为分析的完整指南

恶意代码分析实战:从PE结构、脱壳到API行为分析的完整指南

1. 恶意代码分析实战:从入门到精通的必经之路如果你对网络安全、逆向工程或者恶意软件研究感兴趣,那么“恶意代码分析实战”这个标题对你来说,绝对不是一个陌生的词汇。它更像是一个标志,标志着你从理论走向实践,从旁观…

2026/8/5 12:26:32 阅读更多 →
Unity物理相机Lens Shift七大配置错误解析与避坑指南

Unity物理相机Lens Shift七大配置错误解析与避坑指南

1. 项目概述:为什么物理相机的Lens Shift是个“甜蜜的陷阱”?在Unity里做项目,尤其是涉及到建筑可视化、产品展示或者需要特定镜头语言的游戏时,物理相机(Physical Camera)几乎是绕不开的利器。它能模拟真实…

2026/8/5 12:26:32 阅读更多 →
Open Claw实战:打造移动端高性能数字展馆的完整技术方案

Open Claw实战:打造移动端高性能数字展馆的完整技术方案

1. 项目缘起:当“随时随地”遇上“数字展馆” 最近几年,我身边做文旅、文博、策展的朋友,几乎都在聊同一个词:线上化。这背后是一个很现实的痛点——物理展馆再好,也受限于时间、空间和承载量。一个顶级的特展&#xf…

2026/8/5 12:26:32 阅读更多 →
OpenClaw 卸载指南:Windows、macOS、Linux 及 Node.js 环境深度清理

OpenClaw 卸载指南:Windows、macOS、Linux 及 Node.js 环境深度清理

1. 为什么“卸载”比“安装”更值得你花时间? 如果你在开发或者运维的圈子里待过一阵子,肯定听过这句话:“安装一时爽,卸载火葬场”。OpenClaw 作为一个功能强大的工具,它的安装过程可能被各种教程包装得光鲜亮丽&…

2026/8/5 12:25:32 阅读更多 →

日新闻

Java缓存框架:JetCache

Java缓存框架:JetCache

TOC 一、简介 JetCache 是一个 Java 缓存抽象框架,为不同的缓存解决方案提供了统一的使用方式。 它提供的注解比 Spring Cache 更加强大。 JetCache 的注解支持原生 TTL、两级缓存以及在分布式环境中的自动刷新功能,同时你也可以通过代码直接操作 Cach…

2026/8/5 0:00:43 阅读更多 →
AD 铺铜设置十字连接,过孔全连接,新版AD的简单设置

AD 铺铜设置十字连接,过孔全连接,新版AD的简单设置

需求:通孔焊盘 十字花;过孔 Via 实心直连;贴片焊盘按需设置 AD 测试版本AD24 很多工程师踩坑:全部统一十字,导致接地过孔阻抗高、大电流发热! 一、快捷键打开规则 PCB 界面按下:D R 展开…

2026/8/5 0:00:43 阅读更多 →
AI素描转换技术深度拆解(2024最新论文+工业级落地代码):从Stable Diffusion ControlNet到LoRA微调全链路解析

AI素描转换技术深度拆解(2024最新论文+工业级落地代码):从Stable Diffusion ControlNet到LoRA微调全链路解析

更多请点击: https://kaifayun.com 第一章:AI生成素描效果 AI生成素描效果是计算机视觉与风格迁移技术融合的典型应用,其核心在于将彩色照片或RGB图像转换为具有手绘质感、明暗对比强烈、边缘清晰的单色素描图像。该过程通常依赖于深度学习模…

2026/8/5 0:00:43 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/4 13:24:41 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/4 11:41:39 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/5 10:20:36 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/4 13:38:24 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/4 11:09:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/4 13:38:40 阅读更多 →