指针的学习1
目录
什么是指针?
野指针
造成野指针的原因:
如何避免野指针?
内存和指针
如何理解编址?
指针变量和地址
取地址操作符&
指针变量和解引用操作符
指针变量
如何拆解指针类型?
指针变量的大小
指针变量类型的意义
指针的解引用
指针+整数
void*指针
void* 类型的指针有什么用呢?
const修饰指针
const修饰变量
const修饰指针变量
指针运算
指针+-整数
指针-指针
指针的关系运算
assert断言
使用assert()有几个好处:
指针的使用和传址调用
strlen的模拟实现
传值调用和传址调用
什么是指针?
指针(pointer)是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值,由于通过地址能找到所需的变量单位,可以说,地址指向该变量单位,因此,将地址形象化的称为“指针”,意思是,通过它能找到以它为地址的内存单元
指针是一个变量,存放内存单元的地址(编号)
#include <stdio.h>
int main()
{int a = 10;//在内存中开辟一组空间int* p = &a;//将a的地址存放在p变量中,p就是一个指针变量return 0;
}
野指针
野指针:指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
造成野指针的原因:
- 指针未初始化;
- 指针越界访问;
- 指针指向内存空间释放;
如何避免野指针?
- 指针初始化;
如果明确知道指针指向哪里就直接赋值地址,如果不知道指针应该指向哪里,可以给指针赋值NULL
NULL是C语言中定义的一个标识符常量,值是0,0也是地址,这个地址是无法使用的,读写该地址会报错
- 小心指针越界;
- 指针指向空间释放即使置NULL;指针使用之前检查有效性
当指针变量指向一块区域的时候,我们可以通过指针访问该区域,后期不再使用这个指针访问空间的时候,我们可以把该指针置为NULL,因为约定俗成的一个规则就是:只要是NULL指针就不去访问,同时使用指针之前可以判断指针是否为NULL
- 避免返回局部变量的地址
内存和指针
计算机上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中
把内存划分为一个个的内存单元,每个内存单元的大小取1个字节
1byte=8bit(bit是最小的内存单元)
一个比特位可以存储一个2进制的位1或者0
内存单元的编号=地址=指针
如何理解编址?
首先,必须理解,计算机内有很多的硬件单元,这些硬件单元要互相协同工作。所谓的协作,至少相互之间要能够进行数据传递
但是,硬件与硬件之间是相互独立的,需要用“线”进行通信
CPU和内存之间也是有大量的数据交互的,所以两者必须用线连起来-地址总线
CPU访问内存中的某个字节空间,必须知道这个字节空间在内存的什么位置,而内存中字节很多,需要给内存进行编址
计算机中的编址,并不是把每个字节的地址记录下来,而是通过硬件设计完成的
32位机器有32根地址总线,每根线有两种状态,表示0或1(电脉冲有无),一根线表示2种含义,2根线表示4种含义,32根地址线表示2^32种含义,每一种含义代表一个地址
地址信息被下达给内存,在内存上就可以找到该地址对应的数据,将数据通过数据总线传入CPU内寄存器
指针变量和地址
取地址操作符&
在C语言中创建变量其实就是向内存申请空间
&a取出的是a所占4个字节中地址较小的字节地址
指针--地址
指针变量--存放地址的变量
指针变量和解引用操作符
指针变量
通过取地址操作符(&)拿到的地址是一个数值,这个数值需要存放在指针变量中
指针变量也是一种变量,这种变量是用来存放地址的,存放在指针变量中的值都会理解为地址
指针变量中存储的是一个地址,指向同类型的一块内存空间
如何拆解指针类型?
int a=10;
int* pa=&a;
pa左边写的是int*,*说明pa是指针变量,前面的int说明pa指向的是整型(int)类型的对象
int main()
{int a = 10;int* p = &a;*p = 0;//*解引用操作符(间接访问操作符)//*&a=0;printf("%d", a);//0return 0;
}
指针变量的大小
32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后是1或0,把32根地址线产生的2进制序列当作一个地址,那么一个地址就是32个bit位,需要4个字节才能存储
如果指针变量是用来存放地址的,那么指针变量的大小就得是4个字节的空间才可以
同理,64位机器,假设有64根地址线,一个地址就是64个二进制位组成的二进制序列,存储起来就需要8个字节的空间,指针变量的大小就是8个字节
指针变量--存放地址的
一个字节对应一个地址
指针用来存放地址,地址是唯一标示一块地址空间的
总结:
1.32位平台下地址是32个bit位,指针变量大小是4个字节
2.64位平台下地址是64个bit位,指针变量大小是8个字节
3.注意指针变量的大小和类型是无关的,只要是指针类型的变量,在相同的平台下大小都是相同的
指针变量类型的意义
指针的解引用
指针类型决定了指针进行解引用操作时,能够访问空间的大小(对指针解引用的时候有多大的权限--一次能操作几个字节)
int* p;*p能够访问4个字节
char* p;*p能够访问1个字节
doble* p;*p能够访问8个字节
指针+整数
指针类型决定了,指针走一步能走多远(指针的步长,单位是字节)
void*指针
void* 无具体类型的指针(或者泛型指针),这种类型的指针可以用来接受任意类型的地址,但也有局限性,void* 类型的指针不能进行指针的+-整数和解引用的运算
void* 类型的指针有什么用呢?
一般void* 类型的指针是使用在函数参数的部分,用来接收不同类型数据的地址,这样的设计可以实现泛型编程的效果,使得一个函数来处理多种类型的数据
const修饰指针
const修饰变量
变量不再被改变,变量有了常属性,本质仍是变量,常变量(在C++中,const修饰的变量就是常量)
如果要修改变量,就要通过指针来修改,这样就打破了const的限制,是不合理的,所以应该让变量的地址也不能被修改
const修饰指针变量
const修饰指针变量,可以放在*的左边,也可以放在*的右边,意义是不一样的
int main()
{int a = 10;int b = 20;int* const p = &a;//const在*右边//p=&b;//err*p = 100;printf("%d", a);return 0;
}
- const限制的是指针变量本身,指针变量不能再指向其他变量了,但是可以通过指针变量,修改指针变量指向的内容
int main()
{int a = 10;int b = 20;int const* p = &a;//const在*右边printf("p=%d\n", p);p=&b;//*p = 100;//errprintf("p=%d", p);return 0;
}
运行结果:
- const放在*左边,限制的是:指针指向的内容,不能通过指针来修改指向的内容,但是可以修改指针变量本身的值(修改指针变量的指向)
*两边可以同时加const
指针运算
指针的作用就是访问内存的
指针的基本运算有三种:
- 指针+-整数
- 指针-指针
- 指针的关系运算
指针+-整数
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* p = &arr[0];int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);for (i = 0; i < sz; i++){/*printf("%d ", *p);p++;*///等同于下面一句:printf("%d ", *(p + i));//p没有变化}return 0;
}
指针-指针
指针-指针的绝对值是:两个指针之间的元素个数;指针+指针无意义
计算的前提是:两个指针指向了同一块空间
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int my_strlen(char* str)
{char* start = str;while (*str != '\0'){str++;}return str - start;//指针-指针
}
int main()
{//strlen-求字符串长度,‘\0’之前的字符个数char arr[] = "abcdef";int len = my_strlen(arr);printf("%d", len);return 0;
}
指针的关系运算
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(arr) / sizeof(arr[0]);int* p = arr;//&arr[0]while (p < arr + sz){printf("%d ", *p);p++;}return 0;
}
assert断言
assert.h头文件定义了宏assert(),用于在运行时确保程序符合指定条件,如果不符合,就报错终止运行,这个宏常常被称为“断言”
assert(p != NULL);
上面代码在程序运行到这一行语句时,验证变量是否等于NULL,如果不等于NULL,程序继续运行,否则就会终止运行,并且会给出报错信息提示
assert()宏接受一个表达式作为参数,如果该表达式为真(返回值非零),assert()不会产生任何作用,程序继续运行。如果该表达式为假(返回值为0),assert()就会报错,在标准错误流stderr中写入一条错误信息,显示没有通过的表达式,以及包含这个表达式的文件名和行号
使用assert()有几个好处:
assert()的使用对程序员是非常友好的,它不仅能自动标识文件和出问题的行号,还有一种无需更改代码就能开启或关闭assert()的机制。如果已经确认程序没有问题,不需要再做断言,就在#include <assert.h>语句的前面,定义一个宏NDEBUG
#define NDEBUG
#include <assert.h>
然后,重新编译程序,编译器就会禁用文件中所有的assert()语句,如果程序又出现问题,可以移除这条#define NDEBUG指令(或者把它注释掉),再次编译,这样就重新启用了assert()语句
assert的缺点是:因为引入了额外的检查,增加了程序的运行时间
一般我们可以在Debug中使用,在Release版本中选择禁用assert就行,在VS这样的集成开发环境中,在Release版本中,直接优化掉了,这样在Debug版本写有利于程序员排查问题,在Release版本不影响用户使用时程序的效率
指针的使用和传址调用
strlen的模拟实现
size_t my_strlen(const char* str)//size_t无符号的整型
{size_t count = 0;assert(str != NULL);while (*str != '\0'){count++;str++;}return count;
}
int main()
{char arr[] = "abcdef";size_t len = my_strlen(arr);printf("%d", len);return 0;
}
传值调用和传址调用
下面看一个典型代码,曾几何时,我被它坑过:
void Swap(int x, int y)
{int temp = x;x = y;y = temp;
}
int main()
{int a = 10;int b = 20;printf("交换前:a=%d,b=%d\n", a, b);Swap(a, b);//传值调用printf("交换后:a=%d,b=%d", a, b);return 0;
}
当实参传递给形参的时候,形参是实参的一份临时拷贝,对形参的修改不会影响实参
如果要交换两个数的值,参考以下代码:
void Swap(int* pa, int* pb)
{int temp = *pa;*pa = *pb;*pb = temp;
}
int main(){int a = 10;int b = 20;printf("交换前:a=%d,b=%d\n", a, b);Swap(&a, &b);//传址调用printf("交换后:a=%d,b=%d", a, b);return 0;
}
相关文章:

指针的学习1
目录 什么是指针? 野指针 造成野指针的原因: 如何避免野指针? 内存和指针 如何理解编址? 指针变量和地址 取地址操作符& 指针变量和解引用操作符 指针变量 如何拆解指针类型? 指针变量的大小 指针变量…...

c++:敲桌子
先输出1-100数字,从100个数字中找到这些特殊数字改为敲桌子。 特殊数字:1.7的倍数 2.十位数上有7 3.个位数上有7 #include<iostream> using namespace std; int main() {for (int i 1; i < 100; i) {if (i / 10 7 || i % 10 7|| i % 7 0)…...

Linux中判断文件系统的方法
文章目录 Linux中判断文件系统的方法1.使用mount命令2.使用blkid命令3.使用file命令4.使用fstab文件5.使用df命令(这个用的比较多)6.使用fsck命令7.使用lsblk命令(推荐-简单好用) Linux中判断文件系统的方法 1.使用mount命令 # 这样查看的只有已经挂载…...

聊聊ClickHouse MergeTree引擎的固定/自适应索引粒度
前言 我们在刚开始学习ClickHouse的MergeTree引擎时,就会发现建表语句的末尾总会有SETTINGS index_granularity 8192这句话(其实不写也可以),表示索引粒度为8192。在每个data part中,索引粒度参数的含义有二…...

20240202在WIN10下使用whisper.cpp
20240202在WIN10下使用whisper.cpp 2024/2/2 14:15 【结论:在Windows10下,确认large模式识别7分钟中文视频,需要83.7284 seconds,需要大概1.5分钟!效率太差!】 83.7284/4200.1993533333333333333333333333…...

【Linux】基本指令(上)
🦄个人主页:修修修也 🎏所属专栏:Linux ⚙️操作环境:Xshell (操作系统:CentOS 7.9 64位) 目录 Xshell快捷键 Linux基本指令 ls指令 pwd指令 cd指令 touch指令 mkdir指令 rmdir指令/rm指令 结语 Xshell快捷键 AltEnter 全屏/取消全屏 Tab 进…...
【DB2】—— 一次关于db2 sqlcode -420 22018的记录
情况描述 在DB2 10.5数据库中执行以下SQL语句: SELECT * FROM aa WHERE aa.ivc_typ IN (213,123,12334,345)其中aa.ivc_typ列的类型为VARCHAR(10) 关于执行会发生以下情况 类型转换:SQL引擎会尝试把IN列表中的整数常量转换为VARCHAR(10)类型…...

账簿和明细账
目录 一. 账簿的意义和种类二. 明细账 \quad 一. 账簿的意义和种类 \quad 账簿是由一定格式、互有联系的账页组成,以审核无误的会计凭证为依据,用来序时地、分类地记录和反映各项经济业务的会计簿籍(或称账本)。设置和登记账簿是会计工作的重…...

C# Onnx GroundingDINO 开放世界目标检测
目录 介绍 效果 模型信息 项目 代码 下载 介绍 地址:https://github.com/IDEA-Research/GroundingDINO Official implementation of the paper "Grounding DINO: Marrying DINO with Grounded Pre-Training for Open-Set Object Detection" 效果 …...

PyCharm / DataSpell 导入WSL2 解析器,实现GPU加速
PyCharm / DataSpell 导入WSL2 解析器的实现 Windows的解析器不好么?设置WSL2和实现GPU加速为PyCharm / DataSpell 设置WSL解析器设置Interpreter Windows的解析器不好么? Windows上的解析器的确很方便,也省去了我们很多的麻烦。但是WSL2的解…...
Android矩阵Matrix裁切setRectToRect拉伸Bitmap替代Bitmap.createScaledBitmap缩放,Kotlin
Android矩阵Matrix裁切setRectToRect拉伸Bitmap替代Bitmap.createScaledBitmap缩放,Kotlin class MyImageView : AppCompatImageView {private var mSrcBmp: Bitmap? nullprivate var testIV: ImageView? nullconstructor(ctx: Context, attrs: AttributeSet) :…...

TensorFlow2实战-系列教程11:RNN文本分类3
🧡💛💚TensorFlow2实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Jupyter Notebook中进行 本篇文章配套的代码资源已经上传 6、构建训练数据 所有的输入样本必须都是相同shape(文本长度,…...

故障诊断 | 一文解决,RF随机森林的故障诊断(Matlab)
效果一览 文章概述 故障诊断 | 一文解决,RF随机森林的故障诊断(Matlab) 模型描述 随机森林(Random Forest)是一种集成学习(Ensemble Learning)方法,常用于解决分类和回归问题。它由多个决策树组成,每个决策树都独立地对数据进行训练,并且最终的预测结果是由所有决策…...
DAO设计模式
概念:DAO(Data Access Object) 数据库访问对象,**面向数据库SQL操作**的封装。 (一)场景 问题分析 在实际开发中,针对一张表的复杂业务功能通常需要和表交互多次(比如转账)。如果每次针对表的…...
【Midjourney】新手指南:参数设置
1.--aspect 或 --ar 用于设置图片长宽比,例如 --ar 16:9就是设置图片宽为16,高为9 2.--chaos 用于设置躁点,噪点值越高随机性越大,取值为0到100,例如 --chaos 50 3.--turbo 覆盖seetings的设置并启用极速模式生成…...

阿里云a10GPU,centos7,cuda11.2环境配置
Anaconda3-2022.05-Linux-x86_64.sh gcc升级 centos7升级gcc至8.2_centos7 yum gcc8.2.0-CSDN博客 paddlepaddle python -m pip install paddlepaddle-gpu2.5.1.post112 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html 报错 ImportError: libssl.so…...

RTSP/Onvif协议视频平台EasyNVR激活码授权异常该如何解决
TSINGSEE青犀视频安防监控平台EasyNVR可支持设备通过RTSP/Onvif协议接入,并能对接入的视频流进行处理与多端分发,包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等多种格式。在智慧安防等视频监控场景中,EasyNVR可提供视频实时监控直播、云端…...
React16源码: React中event事件对象的创建过程源码实现
event 对象 1 ) 概述 在生产事件对象的过程当中,要去调用每一个 possiblePlugin.extractEvents 方法现在单独看下这里面的细节过程,即如何去生产这个事件对象的过程 2 )源码 定位到 packages/events/EventPluginHub.js#L172 f…...

深度学习(12)--Mnist分类任务
一.Mnist分类任务流程详解 1.1.引入数据集 Mnist数据集是官方的数据集,比较特殊,可以直接通过%matplotlib inline自动下载,博主此处已经完成下载,从本地文件中引入数据集。 设置数据路径 from pathlib import Path# 设置数据路…...

AI工具【OCR 01】Java可使用的OCR工具Tess4J使用举例(身份证信息识别核心代码及信息提取方法分享)
Java可使用的OCR工具Tess4J使用举例 1.简介1.1 简单介绍1.2 官方说明 2.使用举例2.1 依赖及语言数据包2.2 核心代码2.3 识别身份证信息2.3.1 核心代码2.3.2 截取指定字符2.3.3 去掉字符串里的非中文字符2.3.4 提取出生日期(待优化)2.3.5 实测 3.总结 1.简…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...