C++ 复合数据类型:指针

news2025/2/2 1:44:24

文章目录

  • 指针
    • 用法
    • 无效指针
    • 空指针
    • void *ptr
    • 指向指针的指针
    • 指向常量的指针
    • 指针常量
    • 指针和数组
      • 指针数组和数组指针

指针

计算机中的数据都存在内存中,访问内存的最小单元是“字节”,所有数据,就保存在内存中具有连续编号的一串字节中。
在这里插入图片描述
指针顾名思义就是指向另一种数据类型的复合类型。指针是C/C++中保存另一个数据对象在内存中的“地址”。通过指针可以访问到指向的那个数据对象,所以这是一种间接访问对象的方法。
指针的定义语法形式:类型* 指针变量;
类型是指针指向的对象的类型。
例如:以下 int 类型占4个字节,char占1个字节,指针占8个字节,指针里存的是a的地址:
00 00 00 34 F7 EF F8 88
在这里插入图片描述

#include<iostream>

using namespace std;

int main()
{
    //定义指针
    int *p1;
    long *p2;
    long long *p3;

    cout << "p1长度:" << sizeof(p1) << endl;
    cout << "p2长度:" << sizeof(p2) << endl;
    cout << "p3长度" << sizeof(p3) << endl;
    //指针存放的都是地址,因此它的长度只与系统有关,而不是与类型有关
    //此处输出都是8

}

用法

//指针的使用
int a = 10;
int b = 20;
long c = 88;

p1 = &a; //p1指针指向a
p2 = &c;
cout << "p1:" << p1 << endl;
cout << "p2:" << p2 << endl;

//如何通过指针获取内容
cout << "*p1:" << *p1 << endl;  //*p1:10
cout << "*p2:" << *p2 << endl;  //*p2:88
*p1 = 33;
cout << "a:" << a << "\t*p1:" << *p1 << endl;  //a:33    *p1:33

无效指针

定义一个指针后,如果不进行初始化,指针的内容就是不确定的。如果这时把它的内容当成一个地址去访问,那访问的是不存在的对象;如果访问到的是系统核心区域,修改其中的内容就有可能导致系统崩溃。这样的指针就是“无效指针”,也被叫做“野指针”。

int *p1;
//*p1 = 100   //直接解引用,危险!指针没有初始化,是无效指针

空指针

如果先定义了一个指针,但不确定它要指向哪一个对象,可以先初始化为“空指针”。空指针不指向任何对象。

//空指针
int *np = nullptr;  //空指针的字面值常量,推荐使用
np = NULL;  //预处理变量
np = 0; //只有0可以初始化,让其指向一个未被使用的内存

int zero = 0;
//np = zero  //该初始化行不通

void *ptr

// void *ptr
int a = 10;
char b = 'c';
long d = 67.2;

int *p1 = &a; //p1只能指向int类型

//想要一个能指向任意类型的指针
void *ptr;
ptr = &a;
ptr = &b;
ptr = &c;

// cout << *ptr << endl; //错误,void类型指针只能用来存储地址,但是不能解引用


指向指针的指针

也叫“二级指针”,用连续两个“*” 表示,如果是三级指针则用三个表示。
在这里插入图片描述

    // 指向指针的指针
    int i = 22;
    int *p5 = &i;
    int **pp5 = &p5;

    cout << "i:\t" << i << endl;
    cout << "p5:\t" << p5 << endl;
    cout << "pp5:\t" << pp5 << endl;
    cout << "*p5:\t" << *p5 << endl;
    cout << "*pp5:\t" << *pp5 << endl;
    cout << "**pp5:\t" << **pp5 << endl;

/*输出
i:      22
p5:     0x61fdc8
pp5:    0x61fdc0
*p5:    22
*pp5:   0x61fdc8
**pp5:  22
*/

指向常量的指针

//指向常量的指针
const int i = 10, j = 20;
const int *p = &i;
cout << "p\t" << p << endl;
cout << "*p\t" << *p << endl;
//*p = 15 //错误,常量不可修改
p = &j;  //但是指针指向的对象可以换
cout << "*p\t" << *p << endl;

指针常量

int x = 10; 
int y = 20; 
int *const ptr = &x; // 定义一个指向整型变量的指针常量,指向 x

cout << "x 的值为:" << x << endl;
cout << "通过指针访问 x 的值:" << *ptr << endl;

// 尝试修改指针指向的地址
// ptr = &y; // 这行代码会导致编译错误,因为 ptr 是一个指针常量,不能再指向其他地址

// 通过指针修改所指向地址的内容
*ptr = 100;
cout << "修改后,x 的值为:" << x << endl;

指针和数组

用到数组名时,编译器一般都会把它转换为指针,这个指针就指向数组第一个元素。所以也可以用数组名给指针赋值

//指针和数组的关系
int arr[5] = {1, 2, 4, 5, 6};
cout << "&arr\t" << &arr << endl;
cout << "arr\t" << arr << endl;
cout << "&arr[0]\t" << &arr[0] << endl;
cout << "arr+1\t" << arr + 1 << endl; // arr+1 相当于是arr[1]的地址
cout << "&arr[1]\t" << &arr[1] << endl;

int *ptr = arr;
cout << "ptr\t" << ptr << endl;
cout << "*ptr\t" << *ptr << endl;
cout << "ptr+1\t" << ptr + 1 << endl;
cout << "*(ptr + 1)\t" << *(ptr + 1) << endl;
   
输出:
&arr    0x61fe00
arr     0x61fe00
&arr[0] 0x61fe00
arr+1   0x61fe04
&arr[1] 0x61fe04
ptr     0x61fe00
*ptr    1
ptr+1   0x61fe04
*(ptr + 1)      2

指针数组和数组指针

int arr[5] = {1, 2, 3, 4, 6};
//指针数组,本质是数组,数组的所有的元素都是同类型的指针
int *pa[5]; 
cout << "sizeof(pa)\t" << sizeof(pa) << endl;
pa[0] = arr;
pa[1] = arr +1;
cout << "pa[0]\t" << pa[0] << endl;
cout << "*pa[0]\t" << *pa[0] << endl;

输出
sizeof(pa)      40
pa[0]   0x61fe00
*pa[0]  1

//数组指针,本质是指针,指向一个数组 
int (*ap)[5] = &arr;
cout << "sizeof(ap)\t" << sizeof(ap) << endl;
cout << "ap\t" << ap << endl;
cout << "*ap\t" << *ap << endl;
cout << "**ap\t" << **ap << endl;
cout << "*(*ap + 1)\t" << *(*ap + 1) << endl;

输出:
sizeof(ap)      8
ap      0x61fe00
*ap     0x61fe00
**ap    1
*(*ap + 1)      2

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

B039-SpringMVC基础

目录 SpringMVC简介复习servletSpringMVC入门导包配置前端控制器编写处理器实现Contoller接口普通类加注解(常用) 路径问题获取参数的方式过滤器简介自定义过滤器配置框架提供的过滤器 springMVC向页面传值的三种方式视图解析器springMVC的转发和重定向 SpringMVC简介 1.Sprin…

MongoDB 单机安装部署

文章目录 说明1. 下载安装包2. 安装数据库3. 配置 systemctl4. 创建 root 用户 说明 本篇文章介绍 MongoDB 二进制安装的步骤&#xff0c;整个过程还是比较简单。 1. 下载安装包 进入 MongoDB 官网&#xff0c;获取安装包的下载链接&#xff1a; https://www.mongodb.com/tr…

Node.js安装部署

Node.js安装部署 在 Windows 上安装 Node.js1.使用安装程序2.使用包管理器 Chocolatey 安装 在 macOS 上安装 Node.js1.使用 Homebrew 安装 在 Linux 上安装 Node.js1.使用包管理器安装2.使用 Node.js 官方二进制包 安装完成验证 Node.js 是一个基于 Chrome V8 引擎的 JavaScri…

2023年12月21日开发正式版v1.2.3更新·本次更新30多个细节优化·完善丰富后台功能·加入演员关联机制

2023年12月21日开发正式版v1.2.3更新本次更新30多个细节优化完善丰富后台功能加入演员关联机制 产品简介 安卓苹果PCH5四端&#xff0c;蜻蜓z暗影版的衍生级版本&#xff0c;2023年优雅草蜻蜓z冬季雪花限定版&#xff0c;不仅继承了蜻蜓z的精良功能&#xff0c;还特色增加了弹…

基于深度学习的森林火焰烟雾检测系统(含UI界面,yolov8、Python代码,数据集)

项目介绍 项目中所用到的算法模型和数据集等信息如下&#xff1a; 算法模型&#xff1a;     yolov8 yolov8主要包含以下几种创新&#xff1a;         1. 添加注意力机制&#xff08;SE、CBAM等&#xff09;         2. 修改可变形卷积&#xff08;DySnake-主干c…

【Linux 驱动】Linux设备树(四)—— 设备树驱动LED

有了设备树以后&#xff0c;我们可以将寄存器信息保存到设备树&#xff0c;即便是更换了一个设备&#xff0c;我们也无需修改驱动文件&#xff0c;只需要修改设备树文件并重新编译。 下面介绍两种通过设备树驱动 LED 的最简单的方式&#xff0c;这两种方式的主要是设备树中 re…

轻量Http客户端工具VSCode和IDEA

文章目录 前言Visual Studio Code 的插件 REST Client编写第一个案例进阶&#xff0c;设置变量进阶&#xff0c;设置Token 前言 作为一个WEB工程师&#xff0c;在日常的使用过程中&#xff0c;HTTP请求是必不可少的。我们采用的HTTP工具有如下&#xff1a; Postman Insomnia Ap…

从零实现一套低代码(保姆级教程) --- 【4】实现右侧属性面板

摘要 继画布区的实现之后&#xff0c;来到本系列的第四篇文章&#xff0c;如果你没有看过之前的文章&#xff0c;可以建议先看一下第一篇文章&#xff0c;里面介绍了要实现的项目&#xff0c;是否是你要学习的内容&#xff0c;再决定是否要学习这一些列的文章。 从零实现一套低…

雄雄的小课堂微信机器人流程图

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 最近改造了下微信机器人&#xff0c;新版本还未上线&#xff0c;预计下周一&#xff08;12.25&#xff09;左右能上线第一版。 下面是改造之后的流程图 大家可以看看&#xff0c;有疑问可…

【万能技巧】IP知识速通与小技巧~

本文目录 前言一、网络代理IP简介二、IPIDEA 优势2.1 多种类型IP代理2.2 海量纯净代理池2.3 稳定高效数据收集架构 三、IP实操小Tips3.1 查看本地网络IP3.2 使用浏览器IP3.3 使用IPIDEA进行爬虫实操 前言 各位友友&#xff0c;大家好&#xff0c;马上就到2024年了&#xff0c;…

MyBatis 关联查询

目录 一、一对一查询&#xff08;sqlMapper配置文件&#xff09; 1、需求&#xff1a; 2、创建account和user实体类 3、创建AccountMapper 接口 4、创建并配置AccountMapper.xml 5、测试 二、一对多查询&#xff08;sqlMapper配置文件&#xff09; 1、需求&#xff1a;…

充电桩负载测试的影响是什么

充电桩负载测试是评估充电桩性能和稳定性的重要环节&#xff0c;其影响主要体现在以下几个方面&#xff1a; 1. 安全性&#xff1a;充电桩负载测试可以检测充电桩在高负载情况下的电气安全性能&#xff0c;如电压、电流、温度等参数是否在正常范围内。如果充电桩在高负载下出现…

【圣诞】极安云科赠书活动第①期:CTF实战:从入门到提升

【圣诞】极安云科赠书活动第①期&#xff1a;CTF实战:从入门到提升 9787111724834 9787121376955 9787302556275 ISBN编号&#xff1a;9787111724834 书名&#xff1a;CTF实战:从入门到提升 定&#xff1a;99.00元 开本&#xff1a;184&#xff4d;&#xff4d;260&#xff…

Android:安卓学习笔记之OkHttp原理的简单理解和使用

Android OkHttp使用原理的简单理解和使用 OkHttp 0、前言1、请求与响应流程 1.1 请求的封装1.2 请求的发送1.3 请求的调度1.4 请求的处理2、拦截器 2.1 RetryAndFollowUpInterceptor2.2 BridgeInterceptor2.3 CacheInterceptor 2.3.1、HTTP缓存原理2.3.2、强制缓存2.3.3、协商…

Linux网络编程(一):网络基础(下)

参考引用 UNIX 环境高级编程 (第3版)黑马程序员-Linux 网络编程 1. 协议的概念 1.1 什么是协议 从应用的角度出发&#xff0c;协议可理解为 “规则”&#xff0c;是数据传输和数据解释的规则 假设&#xff0c;A、B双方欲传输文件&#xff0c;规定&#xff1a; 第一次&#xff…

云闪付支付:一种新型的移动支付方式

随着科技的发展&#xff0c;我们的生活方式也在不断地改变。其中&#xff0c;移动支付已经成为我们生活中不可或缺的一部分。而在这个领域中&#xff0c;云闪付支付无疑是一种新型的、高效便捷的支付方式。那么&#xff0c;云闪付支付究竟是什么&#xff0c;它又有哪些特点呢&a…

2023年12月23日 十二生肖 今日运势

小运播报&#xff1a;2023年12月23日&#xff0c;星期六&#xff0c;农历十一月十一 &#xff08;癸卯年甲子月乙卯日&#xff09;&#xff0c;法定节假日。 红榜生肖&#xff1a;狗、猪、羊 需要注意&#xff1a;鼠、龙、鸡 喜神方位&#xff1a;西北方 财神方位&#xff…

Java 虚拟机中的内存结构

1 内存结构 1.1 程序计数器 1.1.1 定义 Program Counter Register 程序计数器&#xff08;寄存器&#xff09; 作用&#xff1a;是记住下一条 jvm 指令的执行地址 特点&#xff1a; 是线程私有的&#xff08;每个线程独有自己的一份&#xff09;不会存在内存溢出 1.1.2 作…

c# OpenCV 检测(斑点检测、边缘检测、轮廓检测)(五)

在C#中使用OpenCV进行图像处理时&#xff0c;可以使用不同的算法和函数来实现斑点检测、边缘检测和轮廓检测。 斑点检测边缘检测轮廓检测 一、斑点检测&#xff08;Blob&#xff09; 斑点检测是指在图像中找到明亮或暗的小区域&#xff08;通常表示为斑点&#xff09;&#…

设计模式:循序渐进走入工厂模式

文章目录 前言一、引入二、简单工厂模式1.实现2.优缺点3.扩展 三、工厂方法模式1.实现2.优缺点 四、抽象工厂模式1.实现2.优缺点3.使用场景 五、模式扩展六、JDK源码解析总结 前言 软件设计模式之工厂模式。 一、引入 需求&#xff1a;设计一个咖啡店点餐系统。 设计一个咖啡类…