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

数组名本质与指针运算揭秘

目录

一、数组名的本质

二、特殊情况分析

三、深入理解数组地址

结果分析

四、总结


一、数组名的本质

在上一章节我们使用指针访问数组内容时,有这样的代码:

int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = &arr[0];

        这里我们使用&arr[0]的方式获取了数组第一个元素的地址。但实际上,数组名本身就是数组首元素的地址。我们可以通过以下测试验证:

#include <stdio.h>
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9,10};printf("&arr[0] = %p\n", &arr[0]);printf("arr = %p\n", arr);return 0;
}

        输出结果显示,数组名和数组首元素的地址打印结果完全相同,这证实了数组名就是数组首元素的地址:


二、特殊情况分析

有同学可能会产生疑问:如果数组名是首元素地址,那么下面的代码该如何解释?

#include <stdio.h>
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9,10};printf("%d\n", sizeof(arr));return 0;
}

        输出结果是40(假设int类型占4字节),而不是预期的4或8(指针的大小)。这似乎与前面的结论矛盾。

实际上,数组名作为首元素地址的规则有两个例外情况:

  1. sizeof(数组名):当数组名单独放在sizeof运算符中时,它表示整个数组,计算的是整个数组的大小(字节数)

  2. &数组名:当取地址运算符作用于数组名时,它表示整个数组,取出的是整个数组的地址

除这两种情况外,其他任何地方使用数组名,数组名都表示首元素的地址。


三、深入理解数组地址

有同学可能会进一步测试以下代码:

#include <stdio.h>
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9,10};printf("&arr[0] = %p\n", &arr[0]);printf("arr = %p\n", arr);printf("&arr = %p\n", &arr);return 0;
}

三个打印结果看起来完全相同,这让人困惑:arr&arr到底有什么区别?

要理解这一点,我们需要观察指针运算的行为:

#include <stdio.h>
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9,10};printf("&arr[0] = %p\n", &arr[0]);printf("&arr[0]+1 = %p\n", &arr[0]+1);printf("arr = %p\n", arr);printf("arr+1 = %p\n", arr+1);printf("&arr = %p\n", &arr);printf("&arr+1 = %p\n", &arr+1);return 0;
}

可能的输出结果:(我们切换到32位环境下观察,64位环境比较难观察)

结果分析

  1. &arr[0]&arr[0]+1相差4个字节(一个int的大小)

  2. arrarr+1也相差4个字节,因为&arr[0]arr都表示首元素的地址,+1操作跳过一个元素

  3. &arr&arr+1相差40个字节(整个数组的大小,10个int × 4字节),因为&arr表示整个数组的地址,+1操作跳过整个数组


四、总结

  1. 指针类型决定了指针的差异!!!所以指针运算的结果也不相同!!!

  2. 数组名本质:在大多数情况下,数组名表示数组首元素的地址

  3. 两个例外

    • sizeof(数组名):计算整个数组的大小

    • &数组名:获取整个数组的地址

  4. 指针运算差异

    • 首元素地址+1:跳过一个元素

    • 数组地址+1:跳过整个数组

理解这些概念对于正确使用数组和指针至关重要,特别是在处理多维数组和指针运算时。

http://www.xdnf.cn/news/1309897.html

相关文章:

  • List容器:特性与操作使用指南
  • 零基础学习人工智能的完整路线规划
  • 民法学学习笔记(个人向) Part.5
  • 学习游戏制作记录(制作系统与物品掉落系统)8.16
  • MySQL查询性能慢时索引失效的排查与优化实践
  • Redis缓存
  • 【OpenGL】LearnOpenGL学习笔记09 - 材质、光照贴图
  • 登录与登录校验:Web安全核心解析
  • 【昇腾】单张48G Atlas 300I Duo推理卡MindIE+WebUI方式跑7B大语言模型_20250816
  • 如何在FastAPI中玩转APScheduler,实现动态定时任务的魔法?
  • 【wmi异常】关于taskkill命令提示“错误:找不到” 以及无法正常获取设备机器码的处理办法
  • pytorch例子计算两张图相似度
  • PHP反序列化的CTF题目环境和做题复现第2集_POP链构造
  • 利用Qwen大模型进行c++11并发库的学习,与时俱进!!!!
  • AI安全增强核心技术:提示词防火墙、置信度过滤与知识蒸馏防御
  • 第6问 数据分析领域主要的岗位有哪些?
  • Rust 入门 KV存储HashMap (十七)
  • pdf合并代码
  • 【C++】异常详解(万字解读)
  • FPGA串口通信实现方案
  • Qt QDateTime时间部分显示为全0,QTime赋值后显示无效问题【已解决】
  • 【C++】C++11
  • Maven私服配置模版
  • 深入详解PCB布局布线技巧-去耦电容的摆放位置
  • IOMMU的2级地址翻译机制及多级(2~5)页表查找
  • Python 项目高频设计模式实战指南:从理念到落地的全景剖析
  • 电路方案分析(二十一)笔记本电脑散热风扇参考设计
  • 【运维心得】三步更换HP笔记本电脑外壳
  • 玄机靶场 | 日志分析-Tomcat日志分析
  • Tomcat架构深度解析:从Server到Servlet的全流程揭秘