数组与指针的区别
创作时间:
作者:
@小白创作中心
数组与指针的区别
引用
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));
}
热门推荐
微波炉能加热塑料袋吗
如何进行项目财务分析?这些分析方法在不同项目中有何异同?
中药:优点与缺点剖析
单相电机如何热保护,详解单相电机的热保护方法
去新西兰结婚要办理哪些手续?详解新西兰结婚流程
A股和B股的优缺点分析,优劣势全面解析
微生物培养基的分类和用途|常见标本类型及对应的培养基选择
揭秘B5纸张的神秘尺寸:究竟有多大?
公司财物被盗:企业如何构建完善的内部盗窃防范制度
BMI值的计算公式及意义
汉朝男子结婚年龄法律规定及社会影响
汉代结婚年龄探究:古代社会婚姻习俗与法律法规
金花的秘密:荣格与卫礼贤对中国文化的深度解读
氯雷他定和地氯雷他定有什么区别
客户成功预算分配模型:资源有限情况下的优先级策略
崇宁通宝铜钱:这三个版别价值不菲,收藏家必看!
社会需求,带来产业的发展!聊聊北宋社会经济影响下的钱币文化
电脑开机键一闪一闪打不开?这份详细排查指南请收好
视力检查项目有哪些
初创品牌攻略:快速打开市场提升占有率
心理学:总被欺骗感情?因为你的大脑在制造“他很爱我”的错觉
花毛茛开花时间及花期详解(花期在几月)
基金投资初探:从入门到精通的全攻略
越南芽庄沉香精油的功效与作用与怎么使用?
普洱茶铜钱的价值评估与相关疑问解答
怎样守好职场边界感
适合新手党的搬砖手游推荐 6款轻松入门的搬砖手游合集
2025年,中国人到老挝的入境手续有什么变化,要怎么办理?
中老铁路有群钢铁“戍边人”
自动启停蓄电池和普通蓄电池有什么区别