数组与指针的区别
创作时间:
作者:
@小白创作中心
数组与指针的区别
引用
1
来源
1.
https://www.cnblogs.com/baobaobashi/p/18782230
在C++编程中,数组和指针是两个非常基础且重要的概念。虽然它们在某些情况下可以相互转换,但它们的本质和使用场景却大不相同。本文将通过具体的代码示例,深入探讨数组与指针的区别,帮助读者更好地理解这两个概念。
一、理解数组类型
指针存储的是内存的地址,而内存的地址实际上是一个64位无符号的整数。我们可以发现指针实际上是内存上的一处空间的值保存着另一处空间的地址。
1、算数方法获取相邻内存的值
首先定义 x 和 y 两个变量,然后分别输出他们的地址。
int x = 1;
int y = 123;
cout << &x << endl; //0x7fffffffdf38
cout << &y << endl; //0x7fffffffdf3c
//可以发现,y的地址比x的地址大4,因为int类型占4个字节
第一次尝试:不使用指针,直接通过地址的加减访问。通过x的地址得到了y的值。
uint64_t addr = (uint64_t)&x;
//uint64_t是64位无符号整数类型,(uint64_t)&x是将x的地址强制转换为64位无符号整数类型
cout << addr << endl;
cout << *(int *)(addr + 4) << endl; //0x7fffffffdf3c
//(int *)(addr + 4)是将addr + 4的结果强制转换为int *类型,即int类型的指针
第二次尝试:使用指针,通过指针的加减访问。通过x的地址得到了y的值。
//指针本身就可以通过地址的加减访问
int *p = &x;
cout << p << endl;
cout << *(p + 1) << endl;
//实际此处自动乘了类型大小
//相当于:
cout << *(p + 1 *sizeof(int)) << endl;
//C++提供的语法糖,也可以直接用下标运算符
cout << p[1] << endl;
注意:若没有显式的使用 x 和 y,可能得到结果不对。
int x = 1, y = 123;
//注意:若没有使用x与y,结果可能不对
//因为编译器可能会自动优化,不会给x与y分配地址。
//cout << &x << endl;
//cout << &y << endl;
int *ptr = &x;
cout << *(ptr + 1) << endl;
cout << ptr[1] << endl;
2、数组类型
int arr[5] = {1, 2, 3, 4, 5};
//让ptr指向arr的第一个元素
int *ptr = &(arr[0]);
int *ptr = arr;
//上面两种方式实际一样,将数组直接赋值给指针
//此处注意:数组 != 指针
for(int i = 0; i < 5; i++)
{
cout << *(ptr + i) << endl;
}
二、数组为什么不等于指针
上个问题最后,为什么数组不等于指针,原因在于数组和指针指向的空间不同。指针指向数组第一个元素的地址,数组指向整块空间的地址。例子如下:
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;
cout << sizeof(arr) << endl; //20
cout << sizeof(ptr) << endl; //8
cout << typeid(arr).name() << endl; //A5_i
cout << typeid(ptr).name() << endl; //Pi
//1、大小不同
//第一个输出了数组的大小为20
//第二个是64位系统下指针的大小为8
//2、类型不同
//数组的类型是长度为5的int数组,类型是int[5]
//而指针的类型是int指针,类型是int *
//原因:数组在赋值给指针的时候,做了隐式的转换
int *ptr = (int*)arr; //转成了第一个元素的首地址
//此处指针只是指向了第一个元素而已,并不代表整个数组
有没有指针可以真正指向数组,而不是指向数组第一个元素的地址呢?有。
//先理解数组类型
int arr[5] = {1, 2, 3, 4, 5};
//此处,数组的类型不是int,去掉变量名,得到int[5]类型
//所以,我们定义指向数组的指针的时候,应该时刻记住数组的类型是int[5]
//初次定义:
int* ptr[5]; //不能这样写,这样写就成了指针数组,元素是int指针类型,长度为5(拆开看)
//应该这样写,这种方式才是真正指向数组的指针
//类型为int[5],然后再以指针的定义方式定义
int (*ptr)[5] = &arr;
//输出可以ptr与*ptr发现:
cout << typeid(ptr).name() << endl; //指针本身类型:PA5_i,指向数组的指针
cout << typeid(*ptr).name() << endl; //指针解引用:A5_i,数组本身
在C++中,可以使用using关键字简化理解
//在C++中,可以使用using让可读性变得更高
using Array5 = int[5];
Array5 arr = {1, 2, 3, 4, 5}; //数组类型是int[5]
Array5 *ptr = &arr; //指向数组的指针
cout << typeid(ptr).name() << endl;
cout << typeid(*ptr).name() << endl;
作为参数时,首元素指针与数组指针在传参的区别:
1、首元素指针:
//使用首元素指针,需要指定长度
void clear(int *arr, int len)
//void clear(int arr[], int len) //将形参写成数组形式,实际上这也是指针,而不是数组。
{
memset(arr, 0, len * sizeof(int));
}
2、真正的数组指针:
//使用指向数组的指针
void clear(int (*arr)[5]) //此处不需要额外传递大小
{
memset(arr, 0, sizeof(*arr)); //此处也不用传递大小,因为变量信息已经包含了大小
}
//进一步将指针改成引用,更方便
void clear(int (&arr)[5])
{
memset(arr, 0, sizeof(arr));
}
//C++20中,能直接推导出数组的引用
void clear(auto& arr)
{
memset(arr, 0, sizeof(arr));
}
热门推荐
API接口新手入门指南
“瓦”字的多层含义与文化内涵
山东济宁:走好发展新质生产力的“任城路径”
中科院海洋所团队发现:SWOT卫星显著提升地球重力场反演分辨率
探秘千年古城韵味——深度解析泉州旅游攻略
三个月的比熊宝宝饮食指南(科学喂养让宠物更健康)
深度学习中的梯度消失与解决方案
专家建议:如何正确选择膏药缓解后遗神经痛
窦性心律过速怎样调理
创新驱动,科技赋能:中国运动品牌迎来新篇章
Access如何链接Excel:步骤详解与最佳实践
预防骨质增生的饮食指南:从食材到注意事项
测速仪使用方法是什么?如何提高测速仪的使用准确性?
深入解析激光测速技术:探索激光测速传感器的工作原理
云南白药胶囊多少范围是正确的用量
如何选择VIP域名:提升品牌形象与在线可见性的终极指南
不想起名的小孩怎么办呢—不想取名字的书
蜜蜂的思維方式及哲理啟示
退学后,高中生抑郁症应如何与家人、朋友沟通,寻求支持?
汽车内饰材料有哪些-汽车内饰材料的类型,以及保养
作废清税证明!恢复税务登记!2024年,企业注销大改!
神经科学告诉你:你的腰围大小竟与你的大脑健康有关
元宝树有毒吗?室内养殖指南及风水摆放建议
止回阀H44H、H44W、H44Y型号的区别
牛顿VS爱因斯坦:物理学双峰,谁对人类的贡献更胜一筹?
母乳喂养还是奶粉喂养?新手妈妈总是两难,看看这份科学研究结果
新生儿呼吸急促正常吗?
肾炎的诊断与治疗:从症状识别到科学管理
为什么说什刹海是北京的灵魂?一次把什刹海的前世今生说清楚
自动驾驶中的车辆运动学模型:两轮模型详解