一篇文章学懂C++和指针与链表
指针
目录
指针
C++的指针学习
指针的基本概念
指针变量的定义和使用
指针的所占的内存空间
空指针和野指针
const修饰指针
指针和数组
指针和函数
指针、数组、函数

接下来让我们开始进入学习吧!
C++的指针学习
指针的基本概念
指针的作用:可以通过指针间接访问内存
-
内存编号是从0开始记录的,一般用十六进制数字表示
-
可以利用指针变量保存地址
这个概念和C语言是一模一样的,只要记住指针就是地址。
指针变量的定义和使用
#include<iostream>
using namespace std;
int main()
{int a = 10;int *pa = &a;cout << a << endl;cout << pa << endl;cout << &a << endl;cout << *pa << endl;//可以通过解引用的方式来找到指针指向的内存*pa = 20;//通过指针来改变a的值cout << a << endl;cout << *pa << endl;return 0;
}
输出结果:
10
0x61fe14
0x61fe14
10
20
20
指针的所占的内存空间
指针也是一种数据类型,所以也会占内存空间。
#include<iostream>
using namespace std;
int main()
{int* pa;char* pb;short* pc;long* pd;float* pe;double* pf;cout << sizeof(pa) << endl;cout << sizeof(pb) << endl;cout << sizeof(pc) << endl;cout << sizeof(pd) << endl;cout << sizeof(pe) << endl;cout << sizeof(pf) << endl;return 0;
}
8
8
8
8
8
8
在32位的操作系统中,指针都是占4个字节的空间的。
在64位的操作系统中,指针则都是占8个字节的空间的。
所以看题目或者写代码的时候一定要清楚自己机器的大小和型号。
空指针和野指针
空指针:指针变量指向内存中编号为0的空间
用途:初始化针变量
注意:空指针指向的内存是不可以访间的
示例1:空指针
#include<iostream>
using namespace std;
int main()
{//空指针//空指针用于给指针变量进行初始化int* p = NULL;//2.空指针是不可以进行访问的,//0~255内存编号是系统占用的,使用会错误,因此不可访问cout << *p <<endl;return 0;
}
野指针:指针变量指向非法的内存空间
示例2:野指针
#include<iostream>
using namespace std;
int main()
{int* p = (int*)0x1100;cout << *p << endl;//这里还是无法输出,指向的是非法内存空间int arr[2] = { 1,2 };p = arr[2];//越界访问cout << *p <<endl;return 0;
}
总结:空指针和野指针都不是我们自己申请的空间,因此不要访问。
const修饰指针
const修饰指针的三种情况:
-
const修饰指针——常量指针
-
const修饰常量——指针常量
-
const既修饰指针,又修饰常量
示例:
#include<iostream>
using namespace std;
int main()
{int a = 10;int b = 20;//常量变量//特点:指针的指向可以修改,但是指针指向的值不可以改const int* p1 = &a;a = 0;//*p1也会相应改变p1 = &b;//可以实现*p1 = 0;//不允许//指针常量//特点:指针的指向不可以修改,但是指针指向的值可以改int* const p2 = &a;*p2 = 10;p1 = &b;//不允许*p1 = 0;//可以实现//既修饰指针,又修饰常量//特点:指针的指向不可以修改,但是指针指向的值也不可以改const int* const p3 = &a;p3 = &b;//不允许*p3 = 0;//不允许return 0;
}
指针和数组
作用:利用指针访问数组中元素
一维数组
#include<iostream>
using namespace std;
int main()
{int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };int * p = arr;for(int i = 0;i < 10; i++){cout << *p + i << endl;//用p[i]也可以做到}return 0;
}
二维数组
#include<iostream>
using namespace std;
int main()
{int arr[2][3] = { { 0,1,2 },{ 3,4,5} };int (* parr)[3] = arr;for(int i = 0;i < 2; i++){for(int j = 0;j < 3; j++){cout << (*parr[i]+j)<<endl;}}return 0;
}
指针和函数
作用:利用指针作函数参数,可以修改实参的值
#include<iostream>
using namespace std;
void Swap(int* x,int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
int main()
{//实现a,b交换int a,b;cin >> a >> b;Swap(&a,&b);cout << "a = " << a << endl;cout << "b = " << b << endl;return 0;
}
指针、数组、函数
案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序 如数组:int arr[10]={4,3,6,9,1,2,10,8,7,5}
#include<iostream>
using namespace std;
void bubbleSort(int *p,int sz)
{for(int i = 0;i < sz - 1; i++){for(int j = 0; j < sz - i - 1; j++){//如果j>j+1的数据就要交换if(*(p + j) > *(p + j + 1)){int tmp = *(p + j);*(p + j) = *(p + j + 1);*(p + j + 1) = tmp;}}}
}
//打印数组
void printArray(int * p,int sz)
{for(int i = 0;i < sz; i++){cout << *p + i << " ";}
}
int main()
{//1.创建数组int arr[10];for(int i = 0;i < 10; i++){cin >> arr[i];}//数组长度int sz = sizeof(arr) / sizeof(arr[0]);//2.创建函数bubbleSort(arr,sz);
//3.打印排序后的数组printArray(arr,sz);return 0;
}
链表
学习C++链表
链表的基本概念avi_

数据域1+next地址 ——> 数据域2+next地址 ——> 数据域3+next地址 ——> 数据域4+next地址 ——> 数据域5+next地址 ——> NULL(空)
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。
链表在指定位置插入和删除不需要移动元素,只需要修改指针即可。
查找效率低于数组
链表相对于数组而言,多了指针域空间开销
链表种类:
静态链表 动态链表 单向链表 双向链表 循环链表 单向循环链表 双向循环链表
拿到链表的第一个节点,就相当于拿到整个链表
头节点不保存任何数据
静态链表

静态链表:分配一整片连续的内存空间,各个结点集中安置,逻辑结构上相邻的数据元素,存储在指定的一块内存空间中,数据元素只允许在这块内存空间中随机存放,这样的存储结构生成的链表称为静态链表。也就是说静态链表是用数组来实现链式存储结构,静态链表实际上就是一个结构体数组
实现一个链表
#define _CRT_SECURE_NO_WARNING
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//链表节点类型定义
struct LinkNode
{int data;struct LinkNode *next;
};
void test()
{struct LinkNode node1 = { 10, NULL };struct LinkNode node2 = { 20, NULL };struct LinkNode node3 = { 30, NULL };struct LinkNode node4 = { 40, NULL };struct LinkNode node5 = { 50, NULL };struct LinkNode node6 = { 60, NULL };node1.next = &node2;node2.next = &node3;node3.next = &node4;node4.next = &node5;node5.next = &node6;//连成链表//如何遍历这个链表struct LinkNode *pCurrent = &node1;while(pCurrent != NULL){printf("%d ",pCurrent->data);//指针移动到下一个元素的首地址pCurrent = pCurrent->next;}
}
int main()
{test();return 0;
}
如何遍历这个链表 需要一个pCurrent指针能够指向下一个链表的地址
pCurrent = pCurrent->next
动态链表
这种链表在初始时不一定分配足够的空间, 但是在后续插入的时候需要动态申请存储空间,并且存储空间不一定连续, 在进行插入和删除时则不需要移动元素, 修改指针域即可,所以仍然具有链表的主要优点,链表结构可以是动态地分配存储的,即在需要时才开辟结点的存储空间,实现动态链接。
链表的实现
LinkList.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<stdnool.h>
#include<stdlib.h>
#iddef __cplusplus
#endif//定义节点数据类型struct LinkNode{int data;struct LinkNode *next;}
//初始化链表struct LinkNode * Init_LinkList();//在值为oldval的后面插入一个新的数据newvalvoid InsertByValue_LinkList(struct LinkNode *header,int oldval,int newval);//删除值为val的节点void RemoveByValue_LinkList(struct LinkNode *header,int delValue);//遍历void Foreach_LinkList(struct LinkNode *header);//销毁void Destroy_LinkList(struct LinkNode *header);//清空void Clear_LinkList(struct LinkNode *header);#ifdef __cplusplus
#endif
LinkList.c
#include "LinkList.h"
//初始化链表
struct LinkNode * Init_LinkList()
{//创建头节点struct LinkNode *header = malloc(sizeof(struct LinkNode));header->data = -1;header->next = NULL;//尾部指针struct LinkNode *pRear = header;int val = -1;while(true){printf("输入插入的数据:\n");scanf("%d",&val);if(val == -1){break;}//先创建新节点struct LinkNode *newnode = malloc(sizeof(struct LinkNode));newnode->data = val;newnode->next = NULL;//新节点插入到链表中pRear->next = newnode;//更新尾部指针指向pRear = newnode;}return header;
}
//在值为oldval的位置插入一个新的数据newvalvoid InsertByValue_LinkList(struct LinkNode *header,int oldval,int newval){if(NULL == header){return;}//两个辅助指针变量struct LinkNode *pPrev = header;struct LinkNode *pCurrent = pPrev->next;while(*pCurrent != NULL){if(pCurrent->data == oldval){break;}pPrev = pCurrent;pCurrent = pCurrent->next;}//pCurrent为空那就说明链表中不存在职位oldval的节点if(pCurrent == NULL){return;}//先创建新节点struct LinkNode *newnode = malloc(sizeof(struct LinkNode));newnode->data = newval;newnode->next = NULL;//新节点插入到链表中pPrev->next = newnode;newnode->next = pCurrent;//删除值为val的节点void RemoveByValue_LinkList(struct LinkNode *header,int delValue){if(NULL == header){return;}//两个辅助指针变量struct LinkNode *pRrev = header;struct LinkNode *pCurrent = pRrev->next;//while(pCurrent != NULL){if(pCurrent->data == delValue){break;}//移动两个辅助指针pPrev = pCurrent;pCurrent = pCurrent->next;}if(pCurrent == NULL){return;}//重新建立待删除节点的前驱和后继节点关系pPrev->next = pCurrent->next;free(pCurrent);pCurrent == NULL;}
//遍历void Foreach_LinkList(struct LinkNode *header){if(NULL == header){return;}//辅助指针变量struct LinkNode *pCurrent = header->next;while(pCurrent != Null){printf("%d ",pCurrent->data);pCurrent = pCurrent->next;}}
//销毁void Destroy_LinkList(struct LinkNode *header){if(NULL == header){return;}//辅助指针变量struct LinkNode *pCurrent = header;while(pCurrent != NULL){//先保存当前节点的下一个节点地址struct LinkNode *pNext = pCurrent->next;//释放当前节点内存free(pCurrent);//指针向后移动pCurrent = pNext;}}//清空void Clear_LinkList(struct LinkNode *header){if(NULL == header){return;}//辅助指针变量struct LinkNode *pCurrent = header->next;while(pCurrent != NULL){//先保存当前节点的下一个节点位置struct LinkNode *pNext = pCurrent->next;//释放当前节点内存free(pCurrent);//pCurrent指向下一个节点pCurrent = pNext;}header->next = NULL;}
TestLinkList.c

相关文章:
一篇文章学懂C++和指针与链表
指针 目录 指针 C的指针学习 指针的基本概念 指针变量的定义和使用 指针的所占的内存空间 空指针和野指针 const修饰指针 指针和数组 指针和函数 指针、数组、函数 接下来让我们开始进入学习吧! C的指针学习 指针的基本概念 指针的作用:可…...
TPGS-cisplatin顺铂修饰维生素E聚乙二醇1000琥珀酸酯
TPGS-cisplatin顺铂修饰维生素E聚乙二醇1000琥珀酸酯(TPGS)溶于大部分有机溶剂,和水有很好的溶解性。 长期保存需要在-20℃,避光,干燥条件下存放,注意取用一定要干燥,避免频繁的溶解和冻干。 维生素E聚乙二醇琥珀酸酯(简称TPGS)是维生素E的水溶性衍生物,由维生素E…...
【20230206-0209】哈希表小结
哈希表一般哈希表都是用来快速判断一个元素是否出现在集合里。哈希函数哈希碰撞--解决方法:拉链法和线性探测法。拉链法:冲突的元素都被存储在链表中线性探测法:一定要保证tableSize大于dataSize,利用哈希表中的空位解决碰撞问题。…...
c++11 标准模板(STL)(std::multimap)(一)
定义于头文件 <map> template< class Key, class T, class Compare std::less<Key>, class Allocator std::allocator<std::pair<const Key, T> > > class multimap;(1)namespace pmr { template <class Key, class T…...
python进阶——自动驾驶寻找车道
大家好,我是csdn的博主:lqj_本人 这是我的个人博客主页: lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…...
男,26岁,做了一年多的自动化测试,最近在纠结要不要转行,求指点。?
最近一个粉丝在后台问我,啊大佬我现在26了,做了做了一年多的自动化测试,最近在纠结要不要转行,求指点。首选做IT这条路,就是很普通的技术蓝领。对于大部分来说干一辈子问题不大,但是发不了什么财。如果你在…...
源码级别的讲解JAVA 中的CAS
没有CAS之前实现线程安全 多线程环境不使用原子类保证线程安全(基本数据类型) public class T3 {volatile int number 0;//读取public int getNumber(){return number;}//写入加锁保证原子性public synchronized void setNumber(){number;} }多线程环…...
JUC锁与AQS技术【我的Android开发技术】
JUC锁与AQS技术【我的Android开发技术】 AQS原理 AQS就是一个同步器,要做的事情就相当于一个锁,所以就会有两个动作:一个是获取,一个是释放。获取释放的时候该有一个东西来记住他是被用还是没被用,这个东西就是一个状…...
【问题代码】顺序点的深入理解(汇编剖析+手画图解)
这好像是一个哲学问题。 目录 前言 一、顺序点是什么? 二、发生有关顺序点的问题代码 vs中: gcc中: 三、细读汇编 1.vs汇编如下(示例): 2.gcc汇编如下(示例): 四…...
BinaryAI全新代码匹配模型BAI-2.0上线,“大模型”时代的安全实践
导语BinaryAI(https://www.binaryai.net)科恩实验室在2021年8月首次发布二进制安全智能分析平台—BinaryAI,BinaryAI可精准高效识别二进制文件的第三方组件及其版本号,旨在推动SCA(Software Composition Analysis&…...
nvidia设置wifi和接口
tx-nx设置wifi和接口前言基础知识点1.创建和删除一个wifi连接2. 启动连接和关闭连接代码和调试1. 代码展示2. 调试写到最后前言 针对嵌入式开发,有时候通过QT或PAD跨网络对设备设置WIFI,在此记录下,方便后续的查阅。 基础知识点 1.创建和删…...
PostgreSQL 变化数据捕捉(CDC)
PostgreSQL 变化数据捕捉(CDC)基于CDC(变更数据捕捉)的增量数据集成总体步骤:1.捕获源数据库中的更改数据2.将变更的数据转换为您的消费者可以接受的格式3.将数据发布到消费者或目标数据库PostgreSQL支持触发器&#x…...
Spring 事务【隔离级别与传播机制】
Spring 事务【隔离级别与传播机制】🍎一.事务隔离级别🍒1.1 事务特性回顾🍒1.2 事务的隔离级别(5种)🍒1.3 事务隔离级别的设置🍎二.Spring 事务传播机制🍒2.1 Spring 事务传播机制的作用🍒2.2 事…...
HTTP和HTTPS协议
HTTP协议 HTTP协议是一种应用层的协议,全称为超文本传输协议。 URL URL值统一资源定位标志,也就是俗称的网址。 协议方案名 http://表示的就是协议方案名,常用的协议有HTTP协议、HTTPS协议、FTP协议等。HTTPS协议是以HTTP协议为基础&#…...
day3——有关java运算符的笔记
今天主要学习的内容有java的运算符 赋值运算符算数运算符关系运算符逻辑运算符位运算符(专门写一篇笔记)条件运算符运算符的优先级流程控制 赋值运算符 赋值运算符()主要用于给变量赋值,可以跟算数运算符相结合&…...
Git多人协同远程开发
1. 李四(项目负责人)操作步骤 在github中创建远程版本库testgit将基础代码上传⾄testgit远程库远程库中基于main分⽀创建dev分⽀将 githubleaflife/testgit 共享给组员李四继续在基础代码上添加⾃⼰负责的模块内容 2. 张三、王五(组员&…...
Chapter4:机器人仿真
ROS1{\rm ROS1}ROS1的基础及应用,基于古月的课,各位可以去看,基于hawkbot{\rm hawkbot}hawkbot机器人进行实际操作。 ROS{\rm ROS}ROS版本:ROS1{\rm ROS1}ROS1的Melodic{\rm Melodic}Melodic;实际机器人:Ha…...
python(14)--集合
前言 本篇文章学习的是 python 中集合的基础知识。 集合元素的内容是不可变的,常见的元素有整数、浮点数、字符串、元组等。至于可变内容列表、字典、集合等不可以是集合元素。虽然集合不可以是集合的元素,但是集合本身是可变的,可以去增加或…...
【Spark分布式内存计算框架——Spark Core】4. RDD函数(中)Transformation函数、Action函数
3.2 Transformation函数 在Spark中Transformation操作表示将一个RDD通过一系列操作变为另一个RDD的过程,这个操作可能是简单的加减操作,也可能是某个函数或某一系列函数。值得注意的是Transformation操作并不会触发真正的计算,只会建立RDD间…...
Mysql 数据类型
1、数值数据类型 1.1 整数类型(精确值) INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT MySQL支持SQL标准的整数类型INTEGER (或INT)和SMALLINT。作为标准的扩展,MySQL还支持整数类型TINYINT、MEDIUMINT和BIGINT。下表显示了每种整数类型所需的存储和范围。…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
