数组名与指针的本质区别
在 C 语言中数组名和指针在语法和操作上有很多相似之处但它们本质上是不同的概念。理解它们的区别对于编写正确、高效的代码至关重要。以下从多个维度进行详细分析。一、核心概念与本质区别特性数组名指针本质数组的标识符代表整个数组的内存块。它是一个地址常量其值为数组首元素的地址。变量专门用于存储内存地址。其本身占用内存通常为4或8字节可以指向不同类型的数据。赋值操作不可赋值。数组名是常量不能出现在赋值运算符的左侧。例如int a[10]; a ...;是错误的。可以赋值。指针变量可以指向不同的内存地址。例如int *p; p x;是合法的。sizeof运算得到的是整个数组所占用的内存字节数。例如int arr[10]; sizeof(arr)通常为 10 * sizeof(int)。得到的是指针变量本身所占用的内存字节数即地址的长度。例如int *p; sizeof(p)在32位系统下为4字节64位系统下为8字节。运算符arr得到的是整个数组的地址。其值与arr首元素地址相同但类型不同如int (*)[10]vsint *。p得到的是指针变量自身的地址即二级指针。自增/自减不允许。因为数组名是常量不能进行arr或--arr等操作。允许。指针可以进行、--等算术运算以移动指向的内存位置。作为函数参数退化为指针。当数组名作为函数参数传递时它会退化为指向其首元素的指针。此时函数内部无法通过sizeof获取原数组大小。本身就是指针传递的是指针值的副本。二、代码示例与深入解析1. 声明与初始化int arr[5] {1, 2, 3, 4, 5}; // arr 是数组名代表一个有5个int的连续内存块 int *ptr arr; // ptr 是指针变量被初始化为指向arr的首元素arr[0]关键点ptr可以重新指向其他地方如ptr other_var;但arr始终指向那个大小为5的int数组的起始位置不能被改变。2.sizeof运算的差异#include stdio.h int main() { int arr[10]; int *p arr; printf(sizeof(arr) %zu , sizeof(arr)); // 输出40 (假设int为4字节10*440) printf(sizeof(p) %zu , sizeof(p)); // 输出4 或 8 (取决于系统位数) printf(sizeof(*p) %zu , sizeof(*p)); // 输出4 (解引用后是int类型的大小) return 0; }注释sizeof(arr)计算的是整个数组的大小而sizeof(p)计算的是指针变量本身的大小。3. 地址与指针运算#include stdio.h int main() { int arr[3] {10, 20, 30}; int *p arr; printf(arr %p , (void*)arr); // 输出数组首元素地址 printf(arr[0] %p , (void*)arr[0]); // 同上 printf(p %p , (void*)p); // 同上因为p指向arr[0] // 指针运算 printf(*(p1) %d , *(p1)); // 输出20 (等价于arr[1]) // 数组名也可以用于指针运算在表达式中会退化为指针 printf(*(arr1) %d , *(arr1)); // 输出20 (等价于arr[1]) // 但以下操作有本质区别 // p; // 合法p现在指向arr[1] // arr; // 非法编译错误数组名是常量不能自增 // 运算符的区别 printf(arr %p , (void*)arr); // 整个数组的地址值与arr相同但类型是 int(*)[3] printf(p %p , (void*)p); // 指针变量p自身的地址一个完全不同的地址 return 0; }4. 作为函数参数时的“退化”#include stdio.h void func1(int arr_param[]) { // 形参声明为数组但实际被编译器视为指针 // 警告此处sizeof(arr_param)是指针的大小不是原数组的大小 printf(Inside func1, sizeof(arr_param) %zu , sizeof(arr_param)); } void func2(int *ptr_param) { // 形参声明为指针 printf(Inside func2, sizeof(ptr_param) %zu , sizeof(ptr_param)); } int main() { int my_arr[100]; func1(my_arr); // my_arr 退化为指向 int 的指针 func2(my_arr); // 同上 return 0; }说明两种函数声明方式是等价的。在函数内部无法通过参数得知原始数组的长度通常需要额外传递一个长度参数。三、从编译器角度理解区别编译器在底层处理数组名和指针时有显著差异符号表信息当声明一个数组如int arr[10];时编译器会在符号表中记录arr是一个大小为10 * sizeof(int)的内存区域的标签。而声明指针如int *p;时符号表只记录p是一个指针类型的变量。地址计算对于数组访问arr[i]编译器生成的代码通常是*(arr的基地址 i * sizeof(元素类型))。这个基地址在编译时通常是已知的常量。对于指针访问p[i]编译器需要先从p所在的地址加载出它存储的地址值然后再进行同样的偏移计算。这意味着指针访问通常多一次内存读取操作。常量传播优化由于数组名是常量地址编译器可以进行更多优化例如将arr[5]直接计算为常量地址。而指针的值可能在运行时改变限制了此类优化。四、常见误区与易错点混淆char str[]和char *strchar str1[] Hello; // 在栈上分配一个数组并将字符串常量复制进去。str1可修改内容。 char *str2 World; // str2指向只读数据区的字符串常量。通过str2修改内容是未定义行为。 // str1[0] h; // 合法 // str2[0] w; // 可能引发运行时错误如段错误对二维数组名使用指针运算int matrix[3][4]; int (*p1)[4] matrix; // 正确p1是指向具有4个int的数组的指针 int **p2 matrix; // 错误类型不匹配二维数组名不是二级指针。误用sizeof在函数内部对作为参数传递进来的“数组名”实已退化为指针使用sizeof得到的是指针大小而非数组大小。这是常见的错误来源。五、总结与最佳实践场景建议需要知道数据集合大小使用数组或结构体包含数组以便利用sizeof在定义域内获取完整大小。需要动态内存分配或重指向使用指针配合malloc/free。函数参数传递“数组”实际上总是传递指针。同时传递数组长度作为另一个参数。可以使用int arr[]或int *arr声明形参前者更具可读性。需要遍历元素两者皆可。for(i0; ilen; i) arr[i]或for(parr; parrlen; p)。前者通常更清晰。定义字符串常量若不需修改使用const char *ptr literal;。若需修改使用char arr[] literal;。根本区别记忆口诀数组名是地址常量代表一块连续内存的起始标签指针是地址变量是一个可以存储和改变地址值的盒子。在大多数表达式中数组名会隐式转换退化为指向其首元素的指针但sizeof和操作是例外它们揭示了数组名的原始类型。理解这些区别有助于避免内存访问错误、编写更高效的代码并深入理解C语言的内存模型。参考来源嵌入式 C语言常见面试试题集锦C语言中数组名和指针的区别C语言中数组名和指针的区别及笔试题目【c语言】数组名和指针的区别从编译器角度分析C语言中数组名和指针的区别C语言指针与数组名,C语言指针和数组名区别

相关新闻

Unity与Unreal Engine实战对比:从核心原理到项目选型指南

Unity与Unreal Engine实战对比:从核心原理到项目选型指南

1. 项目概述:引擎之争下的开发者抉择 在游戏开发这个行当里,选引擎是个绕不开的经典话题,就像木匠选趁手的工具。Unity3D和Unreal Engine(虚幻引擎,简称UE)是当前市场上最主流的两大选择,几乎占…

2026/7/24 10:51:38 阅读更多 →
大模型技术解析:从Transformer架构到工程实践

大模型技术解析:从Transformer架构到工程实践

1. 大模型基础概念全景解析 大模型(Large Language Model)作为当前人工智能领域的核心技术范式,本质上是通过海量参数和训练数据构建的深度神经网络系统。这类模型的核心特征在于其规模——参数量通常达到百亿甚至万亿级别,训练数…

2026/7/24 10:51:38 阅读更多 →
连续性学习机制:从神经可塑性到动态知识图谱

连续性学习机制:从神经可塑性到动态知识图谱

1. 项目概述:重新理解学习机制的本质"自下而上的学习:连续性本身就是学习机制"这个标题直指现代学习理论的核心争议。作为一名在认知科学和教育技术交叉领域工作十二年的从业者,我亲历了从离散知识传授到连续性学习范式的转变过程。…

2026/7/24 10:51:38 阅读更多 →

最新新闻

高速ADC性能解析:从开关特性到典型特性,以ADC12DJ5200RF为例

高速ADC性能解析:从开关特性到典型特性,以ADC12DJ5200RF为例

1. 高速ADC性能参数解析:从开关特性到典型特性在雷达、通信、高端测试测量这些对信号保真度要求极高的领域,高速模数转换器(ADC)的性能直接决定了整个系统的“天花板”。我们经常讨论信噪比(SNR)、无杂散动…

2026/7/24 10:58:40 阅读更多 →
开源大语言模型算力投入与本地部署实践指南

开源大语言模型算力投入与本地部署实践指南

Stability AI 创始人近期回顾了公司发展历程,透露其算力资源主要投入于开源大语言模型(LLM)的构建,而非选择短期商业化的“捷径”。这一策略直接影响了开源社区的技术演进路径,尤其体现在 GPT-J 等模型的迭代过程中。对…

2026/7/24 10:58:40 阅读更多 →
ADS8598H高精度多通道数据采集系统:过采样原理与电力自动化应用

ADS8598H高精度多通道数据采集系统:过采样原理与电力自动化应用

1. 项目概述:高精度多通道数据采集的挑战与机遇在工业自动化、电力监控和精密测试测量领域,构建一个高精度、多通道同步的数据采集系统(DAQ)一直是工程师面临的核心挑战。这类系统的核心任务,是将现实世界中的连续模拟…

2026/7/24 10:58:40 阅读更多 →
MSP432E401Y工业物联网MCU实战:从架构解析到以太网、USB、加密开发

MSP432E401Y工业物联网MCU实战:从架构解析到以太网、USB、加密开发

1. 从数据手册到实战:MSP432E401Y为何是工业物联网的“多面手”在嵌入式开发领域,选型往往是一场性能、成本与外设的“博弈”。当你面对一个需要实时控制、网络连接、数据采集,甚至还要兼顾安全加密的工业物联网项目时,传统的单片…

2026/7/24 10:58:40 阅读更多 →
三相电表设计:AMC1106隔离式Δ-Σ调制器原理与应用详解

三相电表设计:AMC1106隔离式Δ-Σ调制器原理与应用详解

1. 项目概述:为什么三相电表设计需要AMC1106?在工业级三相电能计量领域,电流采样方案的选择直接决定了电表的长期精度、可靠性和抗干扰能力。过去,电流互感器因其固有的电气隔离特性而被广泛使用,但它有一个致命的弱点…

2026/7/24 10:58:40 阅读更多 →
LP8754多相降压转换器寄存器配置实战与电源管理优化

LP8754多相降压转换器寄存器配置实战与电源管理优化

1. 项目概述:从芯片手册到实战配置如果你正在为一块高性能的处理器或FPGA设计供电电路,面对动辄几十安培的峰值电流需求,单相降压转换器往往力不从心。纹波电流大、效率低、瞬态响应慢,这些痛点催生了多相降压转换器的广泛应用。我…

2026/7/24 10:57:40 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化,核心特色:三维 X/Y/Z 三轴空间,所有散点分布在 0~10 立方体空间内;散点使用径向渐变实现立体 3D 圆球质感;支持鼠标 / 触屏拖拽画布,…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值,并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻