数组与指针的区别
创作时间:
作者:
@小白创作中心
数组与指针的区别
引用
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种可能原因
初三一模二模三模有什么区别?成绩如何分析哪次接近中考?
黄金价格浮动起落,最低起步价难确定,市场因素影响大
全球十大手表品牌深度解析
马斯克最新动态:突破性创新与未来趋势的全面布局
做衣柜用什么实木最好?常见的实木材质种类及特点介绍
实木衣柜什么木最好?四种常见木材特点全解析
破解“尿骚”之谜,带你告别异味困扰
猫咪必备!伊丽莎白圈,轻松解决各种困扰
男士佩戴手串:白玉与黑玉的选择指南及其文化含义
如何实现录音中人声的清晰化处理?有哪些有效技巧?
高效沟通培训对职业发展的影响有多大?
91制片模式的优势与挑战:如何在低预算下创造高质量影视作品
贴墙砖前一定要做的功课:瓷砖胶与背涂胶的区别
卫生间墙砖粘贴技巧及注意事项
中国海洋大学:海参抗炎肽高通量鉴定工作流程的建立
怎么进行智商检测
高频量化期权期货的定义是什么?它对市场效率有何影响?
氙气灯与LED灯对比:汽车照明技术大解析
定制门窗遇欺诈,商场和品牌方是否担责?法院这样判
南宁生榨米粉:非遗里的独特酸香
工业自动化前景如何
唐代皇帝能力等级顺序表的构建与解读
微型学习:提升学习效率的新方法与实践
虎式坦克详细数据揭秘:重量、动力、装甲全方位解析
龙珠 | 可爱的坏蛋,破坏神比鲁斯:龙珠宇宙中的神秘与力量
深圳地铁8号线三期新进展!2026年贯通全城
肌电图在神经病变中的应用