数组与指针的区别

news/2025/3/20 1:15:52/文章来源:https://www.cnblogs.com/baobaobashi/p/18782230

一、理解数组类型

指针存储的是内存的地址,而内存的地址实际上是一个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));
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/901819.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《自然语言处理实战 : 预训练模型应用及其产品化》 | PDF免费下载

《自然语言处理实战:预训练模型应用及其产品化》系统讲解了 NLP 领域的最新技术,涵盖 BERT、GPT 等预训练模型的应用,并结合实际案例展示如何将 NLP 技术产品化。适合开发者、数据科学家及 AI 从业者,助力高效落地 NLP 解决方案。点击下载 书籍信息 作者: Ankur A. Patel /…

[以太网/汽车网络] 车载服务通信(SOME/IP)设计实践 [转]

序 1 引入在SOA架构中,服务是构成系统的基本单元,它代表了系统中的某个功能或操作。服务通过明确的接口与外界进行交互,实现了功能的封装和重用。 SOA架构的核心就是服务: 它通过将应用程序划分为一系列的服务来降低系统的复杂度,提高系统的灵活性和可维护性。 在SOA中,服…

小白尖叫!DeepSeek安装竟偷占C盘?这样做路径配置 直接根治存储焦虑!

🚀 个人主页 极客小俊 ✍🏻 作者简介:web开发者、设计师、技术分享 🐋 希望大家多多支持, 我们一起学习和进步! 🏅 欢迎评论 ❤️点赞💬评论 📂收藏 📂加关注前言 之前给大家讲解了关于Ollama+DeepSeek的使用和本地部署, 有些朋友表示遇到一些问题,无法解决! …

智能工厂搭建:系统数量与选型的深度剖析

当今制造业加速迈向智能化的时代,智能工厂成为众多企业追求的目标。它宛如一座现代化的智慧堡垒,融合了先进技术与高效管理流程,能大幅提升生产效率、优化产品质量。然而,构建智能工厂并非一蹴而就,其中一个关键且容易让人困惑的问题便是:究竟要引入多少系统?搞懂这一点…

20款好用的SSH客户端工具,你在用哪个?

20款好用的SSH客户端工具,你在用哪个? 有些小伙伴购买了Linux服务器之后,不知道该用什么工具来实现本地连接,而不是每次打开服务器厂家所提供的 web 命令页面来操作。操作步骤:登录账号 - 找到服务器 - 打开web命令页面SSH工具:打开软件 - 配置连接通过SSH工具大大减少了…

Spring AOP 的实现原理

一、AOP的基本概念 将横切关注点(日志、事务、权限)从业务逻辑中分离出来,提高代码的可维护性。 下面将解释,AOP专属名词,切面、连接点、切点、通知、目标对象、代理对象:切面:切面是封装横切关注点的模块,比如日志记录。 @Aspect 修饰类,如 LoggingAspect 连接点:连…

drm study

学习过程 0319:对于任何驱动来说,buffer是最重要的,知道了buffer的创建使用这个驱动就会一半了;现在感觉是一个无头苍蝇,感觉非常复杂:数据结构非常多,之间的关系也非常复杂;不过没关系,先研究buffer通路;可以看见应用层对mmap写入的hello world,驱动中vkms_obj->…

pcie 简介及引脚定义

随着现代处理器技术的发展,在互连领域中,使用高速差分总线替代并行总线是大势所趋。与单端并行信号相比,高速差分信号可以使用更高的时钟频率,从而使用更少的信号线,完成之前需要许多单端并行数据信号才能达到的总线带宽。 PCI总线使用并行总线结构,在同一条总线上的所有…

C++ 基础(1)

0x01 第一个C++程序 #include <iostream>int main() {std::cout << "Hello World!\n"; } // std::cout 向控制台输出内容的指令 // << 输出的运算符 // "" 字符串内容的边界符 // \n 输出换行 // Hello World 输出字符…

在ubuntu系统下与开发板连接问题记录

对我所遇到的问题以及解决方法进行简单的记录在开发板与ubuntu(非虚拟机)连接之后使用lsmod查看是否连接lsusb 我的显示如下:如果可以看到自己的USB设备 那么就说明你已经安装了驱动 如果没有 请安装你的串口对应的驱动 我的驱动是CH340 没有安装的朋友可以去下面网站进行…

maven为什么发生依赖冲突?怎么解决依赖冲突?

maven为什么发生依赖冲突?怎么解决依赖冲突? 我们在开发的时候,偶尔会遇到依赖冲突的时候,一般都是NoClassDefFoundError、ClassNotFoundException、NoSuchMethodError。打开搜索框又发现有这个类,明明就是引入进来了,就是找不到,让人头疼 1. 依赖冲突场景 在maven中依赖…

unstructured

unstructured 是一个开源的 Python 库,专门用于处理非结构化数据,如从 PDF、Word 文档、HTML 文件等中提取文本内容,并将其转换为结构化格式(1)安装依赖库pip install unstructured使用textfrom unstructured.partition.auto import partitionfilename = "a.txt"…