数组与指针的区别
创作时间:
作者:
@小白创作中心
数组与指针的区别
引用
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));
}
热门推荐
从亏损到盈利:每个交易者都应知晓的5条关键裸K交易规则!
民生直通车|破解“发现难” 技术升级赋能结核病防治
中药名方之当归四逆汤
江苏南京:大学生在基层锻炼中奉献青春力量
租房时支付的押金如何取回
马斯克宣布:SpaceX首次实现火箭跨国回收
王者荣耀西施英雄攻略:技能解析与实战技巧
量子力学与佛教哲学:科学与宗教在认知边界的交融
量子奇境VS佛学智慧——正确对待科学与佛学的比较研究
ES6新增Set、Map两种数据结构
印尼旅游必去十大景点,你打卡了几个?
从全球视野看上海国际金融中心建设
存储云端真的安全吗?探讨其安全性与潜在风险
活塞环应如何正确安装?这样的安装方式对发动机有哪些影响?
劳动仲裁2n和n+1的区别
解锁坐姿器械划船训练,打造强大背肌
接连拿下两个影后大奖,90花TOP非她莫属?
《塞尔达传说智慧的再现》新手入门指南:系统说明及实用技巧
四柱福星食神分析:食神在四柱八字中的意义和作用
巧治小儿黄鼻涕的方法是什么?
自闭症如何调整作息
哈希表详解与实现
这些部位长“痘痘”,身体可能预示大问题,别不当回事!
作文如何写长(将作文写得更长的方法)
公司热点|股价大涨!立方数科收监管关注函 业绩连续亏损三年
劳动法维权的六大途径及具体操作指南
广东省云浮市: 传统产业融合现代科技 助力乡村全面振兴
企业如何做市场需求分析?
不吃白人饭,打工人流行吃蒸菜减肥?
如何选择适合自己身高的摩托车?不同坐高的摩托车对驾驶体验有何影响?