数组与指针的区别
创作时间:
作者:
@小白创作中心
数组与指针的区别
引用
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));
}
热门推荐
新车保养周期全攻略:让爱车更耐用的实用指南
<哈利·波特:一段魔法史>新书发布,24年经典再续新篇
机油换季保养指南:让你的车焕发新生
哈利波特魔法觉醒攻略:15种植物功能大揭秘
霍格沃茨之遗魔药攻略:7种配方获取与调制
下五花肉才是炖煮神器!教你做出完美五花肉
快速腌肉,高效美食制作秘籍
炖五花肉,肥而不腻的秘密武器
阴阳平衡的生活:中医养生的日常法则
阴阳平衡:中医理论中的养生智慧解析
精诚医学研发新型骨修复材料,可降解特性避免二次手术
常德四院引进MEDIX90骨密度仪,实现无创快速骨骼健康检测
冬季骨病预防全攻略:运动、营养两手抓
输电线路杆塔倾斜在线监测装置的含义以及安装的意义?
某电力铁塔安全监测预警系统案例分享
输电线路图像在线监测系统的应用与发展
详解路口让行规则:转弯让直行并非绝对
粉色家装热潮来袭,打造温馨梦幻家
粉色治愈力爆表,你get了吗?
粉色潮流席卷时尚圈,减龄神器来了!
东汉铜镜宋代瓷枕:张衡博物馆里的虎文化瑰宝
从音色看音乐创作:情感表达与风格塑造
时空交错的美学:复古未来主义室内设计指南
舞台剧制作全纪实:从排练到谢幕的演艺艺术
面試完感謝信怎麼寫?感謝信架構、注意事項完整解說【附感謝函範本】
夏日必备:凉拌粉丝的N种花样
凉拌粉丝新花样,让你秒变厨艺达人!
牙龈肿痛、张口受限?智齿冠周炎的科学应对指南
智齿不是“无用之齿”,这些情况要当心
石姓溯源:三支起源、千年变迁与当代分布