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

【C++指针】 数组名与指针:为什么datas和sizeof(datas)的行为不同?

一、困惑现场

这段代码有什么问题?

structXData;XData datas[3];unsignedcharbuf[1024]={0};memcpy(buf,&datas,sizeof(datas));

疑问:

  1. datas不就是指针吗?为什么用&datas
  2. sizeof(datas)不是4(指针大小)吗?为什么是数组大小?

二、先看一个简单实验

#include<iostream>usingnamespacestd;intmain(){intarr[5]={1,2,3,4,5};cout<<"arr 的值: "<<arr<<endl;// 输出地址cout<<"&arr 的值: "<<&arr<<endl;// 也是地址cout<<"arr + 1: "<<arr+1<<endl;// 下一个int的地址cout<<"&arr + 1: "<<&arr+1<<endl;// 跳过整个数组cout<<"sizeof(arr): "<<sizeof(arr)<<endl;// 20 (5*4)cout<<"sizeof(&arr): "<<sizeof(&arr)<<endl;// 8 (指针大小)return0;}

输出结果:

arr 的值: 0x7ffc12345670 &arr 的值: 0x7ffc12345670 arr + 1: 0x7ffc12345674 &arr + 1: 0x7ffc12345684 sizeof(arr): 20 sizeof(&arr): 8

三、核心概念:数组名的两种身份

概念1:数组名是首元素地址

intarr[5]={1,2,3,4,5};// arr 是首元素地址int*p1=arr;// ✅ 正确:arr可以赋值给int*p1[0]=100;// 修改第一个元素// arr 不是指针变量,是常量地址// arr = p1; // ❌ 错误:不能修改arr

概念2:&数组名是整个数组的地址

intarr[5];// arr : int* 类型,指向第一个元素// &arr : int(*)[5] 类型,指向整个数组int*p1=arr;// ✅ int* = int*int(*p2)[5]=&arr;// ✅ 数组指针 = &数组名cout<<sizeof(arr)<<endl;// 20:整个数组的大小cout<<sizeof(&arr)<<endl;// 8:指针的大小

四、图解:arr 和 &arr 的区别

内存布局: arr[0] arr[1] arr[2] arr[3] arr[4] [1] [2] [3] [4] [5] 0x100 0x104 0x108 0x10C 0x110 arr (首元素地址) → 0x100 (指向int) &arr (数组地址) → 0x100 (指向整个5个int的数组) arr + 1 → 0x104 (跳过一个int) &arr + 1 → 0x114 (跳过整个数组,5*4=20字节)

五、为什么 memcpy 要用 &datas?

错误写法

XData datas[3];memcpy(buf,datas,sizeof(datas));// ❓ 这样写对吗?

这其实是可以工作的,因为:

  • datas是首元素地址
  • sizeof(datas)是整个数组的大小

为什么用 &datas 更准确?

memcpy(buf,&datas,sizeof(datas));// ✅ 更准确的写法

理由:

  • &datas明确表示"整个数组的地址"
  • 类型是XData(*)[3],强调这是整个数组
  • datas只是首元素地址,类型是XData*

两者的值相同,但类型不同

cout<<(void*)datas<<endl;// 0x100cout<<(void*)&datas<<endl;// 0x100(相同的地址)// 但类型不同// datas : XData*// &datas : XData(*)[3]

六、sizeof 的魔法

为什么 sizeof(datas) 是数组大小?

XData datas[3];// sizeof 是编译时运算符,不是函数!size_t size=sizeof(datas);// = 3 * sizeof(XData)// 原理:编译器知道 datas 是数组类型 XData[3]// 所以在编译时就能计算出整个数组的大小

对比验证

voidtestArray(XData datas[]){// 这里的 datas 已经变成指针了!cout<<sizeof(datas)<<endl;// 输出 8(指针大小)}intmain(){XData datas[3];cout<<sizeof(datas)<<endl;// 输出 3 * sizeof(XData)testArray(datas);// 输出 8}

七、记忆口诀

数组三连

  • 数组名是地址:指向第一个元素
  • &数组名也是地址:指向整个数组
  • sizeof数组名:整个数组的大小

地址计算

  • arr + 1:跳到下一个元素
  • &arr + 1:跳到整个数组后面

拷贝数组

  • 目标:&arr(更准确)
  • 大小:sizeof(arr)(整个数组)

八、面试常考

问题1:下面代码输出什么?

inta[5]={1,2,3,4,5};int*p=(int*)(&a+1);printf("%d",*(p-1));

答案:5

  • &a + 1跳过整个数组,指向数组后面
  • 转成int*再减1,指向最后一个元素

问题2:sizeof 在数组和指针上的区别

intarr[10];int*p=arr;sizeof(arr);// 40 (10*4)sizeof(p);// 8 (指针大小)

数组名有两个身份:作为首元素地址时像指针,作为数组名时代表整个数组。&数组名强调"整个数组"的身份,sizeof(数组名)计算整个数组的大小。memcpy用&数组名是为了语义清晰:我要拷贝整个数组!

http://www.jsqmd.com/news/421073/

相关文章:

  • CI流水线质量门禁的7个关键节点与实施策略
  • 可可收麦德龙购物卡线上回收攻略:避开虚高陷阱,安全回收更省心 - 可可收
  • 从此告别拖延,AI论文工具 千笔写作工具 VS 灵感风暴AI,专科生专属利器!
  • C++中的 赋值和初始化
  • 互联网大厂Java面试场景:从基础到微服务与云原生
  • 实测才敢推AI论文平台,千笔 VS 笔捷Ai,专科生写作更省心!
  • 从全栈开发到微服务架构:一场真实的技术面试
  • 2026年2月防火卷帘门企业推荐,消防验收无忧与合规生产厂家 - 品牌鉴赏师
  • Appium跨平台测试的致命陷阱与系统性规避策略
  • 用过才敢说!专科生必备的降AIGC网站 —— 千笔·降AIGC助手
  • 全自动超声波气象站
  • 可可收科普:闲置立减金别乱处理!这 4 个误区正在坑人 - 可可收
  • 2026年有名的直播带货培训公司推荐,浙江育达教育值得关注 - mypinpai
  • 科研党收藏!圈粉无数的AI论文软件 —— 千笔ai写作
  • 便携式EL测试仪
  • 推荐MySQL中的这10种高级用法
  • 2026口碑不错的装饰一体板定制厂家排行,别错过,真空绝热板保温装饰一体板,装饰一体板生产厂家推荐 - 品牌推荐师
  • 建议收藏|小白程序员必看:AI 时代不会被淘汰,从零入门大模型应用开发全路径
  • 在线培训考试系统哪个好?全维度选型指南与深度解析
  • 【山海鲸实战案例】通过跟随相机设置无人机视角巡航
  • 分析溪山里酒店创新能力怎么样,在贵阳酒店行业排名如何? - 工业推荐榜
  • 终于有人把牛客网上的Java面试八股文整理成了PDF合集(Java基础+Redis+MySQL+多线程与高并发+JVM+分布式+Spring+微服务)
  • 收藏 | LangGraph+MCP+ReactAgent:小白也能学会构建智能代理系统,解锁大模型进阶玩法
  • 2026年高端月子会所最新推荐:西安金月汇/金月子以标准化领先行业 - 深度智识库
  • 基于PLC的喷泉控制系统设计商品介绍
  • 哪个平台更适合你?独立站社媒引流深度指南
  • 2026年月子中心加盟指南:为何西安金月汇成为行业投资首选? - 深度智识库
  • 2026年江苏好用的公司认证正规企业推荐与选购指南 - 工业设备
  • 从盲目调参到有的放矢:构建机械故障诊断算法的系统性工程思维
  • 2026年月子中心TOP5加盟分析报告:五大机构深度解析与优选策略出炉! - 深度智识库