【理解指针(二)】
文章目录
- 一、指针的运算
- (1)指针加整数
- (2)指针减指针(指针关系运算)
- 二、野指针
- (1)野指针的成因
- (1.1)指针未初始化
- (1.2)指针的越界访问
- (1.3)指针指向的空间释放
- (2)如何避免野指针
- (2.1)指针需要初始化
- (2.2)指针变量不再使用时,及时置NULL,指针使用之前检查有效性
- 三、 strlen的模拟实现
- 四、总结
一、指针的运算
(1)指针加整数
例子,我们打印一组数字:
#include<stdio.h>
int main()
{int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };int* pa = &arr[0];int sz = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < sz; i++){printf("%d ", *(pa + i));}return 0;
}

这里的pa + i就是指针变量加上一个整数,pa + i是地址,*是对这个地址的解引用。
(2)指针减指针(指针关系运算)
#include<stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10};int* pa = &arr[0];printf("%d ", &arr[9] - pa);return 0;
}

上面的代码我们也可以用指针关系运算来写:(这里我们需要用到循环)
#include<stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* pa = &arr[0];int sz = sizeof(arr) / sizeof(arr[0]);while (pa < arr+sz){printf("%d ", *pa);pa++;}return 0;
}
这里的pa < arr+sz是指针的比较,pa就是第一个元素开始的地址,而arr+sz就是最后一个元素结束的地址:

这里的&arr[9] - pa也可以写成&arr[9]-&arr[0],而得到的结果是 9 。由此我们可以得到一个结论:
指针的关系运算,得到的是指针和指针之间元素的个数。
二、野指针
(1)野指针的成因
(1.1)指针未初始化
示范一个错误例子:
#include<stdio.h>int main()
{int* pa;*pa = 1;printf("%d ", *pa);return 0;
}

局部变量指针未初始化,默认为随机值。
(1.2)指针的越界访问
#include<stdio.h>
int main()
{int arr[10] = { 0 };int* pa = &arr[0];for (int i = 0; i <= 11; i++){*(pa++) = i;printf("%d ", *pa);}return 0;
}
指针指向的范围超出数组arr的范围,pa就是野指针(指针指向的范围有11个,而数组arr的范围只有10个)

(1.3)指针指向的空间释放
#include<stdio.h>
int Print()
{int a = 90;return &a;
}
int main()
{int* pa = Print();printf("%d ", *pa);return 0;
}
我们写一个函数,将a赋值为90,然后把a的空间返回到主函数中,*pa可以接受到a的地址,但是出了Print()函数,空间就被回收了,此时*pa带着地址去访问该空间,不会得到任何数字,这就是空间的释放。
(2)如何避免野指针
(2.1)指针需要初始化
- 如果我们明确知道指针指向哪里就直接赋值地址:
#include<stdio.h>
int main()
{int a = 20;int* pa = &a;return 0;
}
这里前面就是知道pa指针指向的是a的地址,所以我们直接:int* pa = &a。
- 如果我们不知道指针应该指向哪里,可以给指针赋值NULL。NULL 是C语⾔中定义的⼀个标识符常量,值是0,0也是地址,这个地址是⽆法使⽤的,读写该地址会报错。
#include<stdio.h>
int main()
{int* p = NULL;*p = 20; //errprintf("%d ", *p);return 0;
}
小心指针的越界:
⼀个程序向内存申请了哪些空间,通过指针也就只能访问哪些空间,不能超出范围访问,超出了就是越界访问。(可以见上面的(1.2))
(2.2)指针变量不再使用时,及时置NULL,指针使用之前检查有效性
#include<stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* pa = &arr[0];for (int i = 0; i < 10; i++){*(pa++) = i;}pa= NULL;pa = &arr[0];if (pa != NULL){for (int i = 0; i < 10; i++){printf("%d ", *(pa + i));}}return 0;
}
当 *(pa++) = i;循环结束后,pa是超出了arr的范围的,此时可以把pa重置;当我们要重新用到pa时,可以让pa重新获得地址,重新获得地址后,我们需要判断pa是不是空指针,以确保代码的安全性。
- 避免返回局部变量的地址(可见(1.3))
三、 strlen的模拟实现
库函数strlen的功能是求字符串长度,统计的是字符串中 \0 之前的字符的个数。
如果要模拟实现只要从起始地址开始向后逐个字符的遍历,只要不是 \0 字符,计数器就+1,这样直到 \0 就停止。
#include<stdio.h>
#include<string.h>
int my_strlen(char* pc)
{int count = 0;while (*pc != '\0'){count++;pc++;}return count;
}
int main()
{char arr[] = { "abcdf" };int len = my_strlen(arr);printf("%d ", len);return 0;
}
上面的代码,我们可以发现有很多的不足之处,不可以确保代码完全的安全性:
-
如果用户不小心把数组传成了空指针

-
int是有符号的整形,它可以为负数,但是我们统计数字不可能是负数
-
char *pc只是用于遍历的,不能对*pc进行修改

所以最后的代码应该改为:
#include<assert.h>
#include<stdio.h>
#include<string.h>
size_t my_strlen( const char* pc)
{assert(pc != NULL);size_t count = 0;while (*pc != '\0'){count++;pc++;}return count;
}
int main()
{char arr[] = { "abcdf" };size_t len = my_strlen(arr);printf("%zd ", len);return 0;
}
四、总结
指针需要理解的东西有很多,希望大家可以自己慢慢去消化,指针这一章的内容还没有结束哟,希望与大家下一次再见。ԅ(¯ㅂ¯ԅ)

相关文章:
【理解指针(二)】
文章目录 一、指针的运算(1)指针加整数(2)指针减指针(指针关系运算) 二、野指针(1)野指针的成因(1.1)指针未初始化(1.2)指针的越界访问…...
使用AI纠正文章
我写了一段关于哲学自学的读书笔记,处于好奇的目的,让AI帮我纠正语法和逻辑。我的原文如下: 泰勒斯第一次提出了水是万物本源的说法,对于泰勒斯为什么提出这样的观点,或者是这样的观点是怎么来的,我们无从所…...
拼多多API批量获取商品详情信息
随着电子商务的蓬勃发展,淘宝作为中国最大的在线购物平台之一,每天需要处理海量的商品上架和交易。为了提高工作效率,自动化上架商品和批量获取商品详情信息成为了许多商家和开发者的迫切需求。本文将详细介绍淘宝的API接口及其相关技术&…...
杨辉三角(C语言)
杨辉三角 一.什么是杨辉三角 一.什么是杨辉三角 每个数等于它上方两数之和。 每行数字左右对称,由1开始逐渐变大。 第n行的数字有n项。 前n行共[(1n)n]/2 个数。 … 当前行的数上一行的数上一行的前一列的数 void yanghuisanjian(int arr[][20], int n) {for (int i…...
宏任务与微任务:JavaScript异步编程的秘密
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
vant van-field 密码输入框小程序里隐藏、显示密码bug总结
老规矩先上效果图: vant 输入框组件 密码的隐藏与显示功能: 注: 用password属性控制密码的显示与隐藏 不要用type属性,type属性在真机上有时会没有效果 1、当然如果只用typepassword 不需要切换显示、隐藏也可以使用。 2、如果用到了密码的显示与…...
代理ip应用场景
代理IP是一种网络技术,它允许用户通过中间来访问互联网资源,隐藏真实的IP地址代理IP的应用场景非常泛,以下是一些常见的应用场景: 1 隐私保护:使用代理IP可以隐藏用户的真实IP地址,保护个人隐私。在浏览网…...
C/C++指针详解
接下来我们来介绍一下什么是指针? 指针其实就是元素存放地址,更加形象的比喻:在酒店中如果你想要去注必须去付费不然不能住,在计算机也同样如此(但是不需要付费哦)每当我们使用一个变量或其他需要申请空间…...
实验一:华为VRP系统的基本操作
1.1实验介绍 1.1.1关于本实验 本实验通过配置华为设备,了解并熟悉华为VRP系统的基本操作 1.1.2实验目的 理解命令行视图的含义以及进入离开命令行视图的方法 掌握一些常见的命令 掌握命令行在线帮助的方法 掌握如何撤销命令 掌握如何使用命令快捷键 1.1.3实验组网 …...
ChatGPT发不出消息?GPT发不出消息怎么办?
前言 今天发现,很多人的ChatGPT无法发送信息,我就登陆看一下自己的GPT的情况,结果还真的无法发送消息,ChatGPT 无法发送消息,但是能查看历史的对话,不过通过下面的方法解决了。 第一时间先打开官方的网站&a…...
【论文笔记】Language Models are Few-Shot Learners
Language Models are Few-Shot Learners 回顾一下第一代 GPT-1 : 设计思路是 “海量无标记文本进行无监督预训练少量有标签文本有监督微调” 范式;模型架构是基于 Transformer 的叠加解码器(掩码自注意力机制、残差、Layernorm)&a…...
解决:Glide 在回调中再次加载图片报错
一、问题说明 Glide 加载图片时监听了回调,并在失败时再次加载其它图片后报错。 代码: Glide.with(mContext).load(imgTeacher).listener(new RequestListener<Drawable>() {Overridepublic boolean onLoadFailed(Nullable GlideException e, O…...
Java学习笔记之IDEA的安装与下载以及相关配置
1 IDEA概述 IDEA全称IntelliJ IDEA,是用于Java语言开发的集成环境,它是业界公认的目前用于Java程序开发最好的工具。 集成环境: 把代码编写,编译,执行,调试等多种功能综合到一起的开发工具。 2 IDEA…...
【共享内存】System V共享内存{通信原理/相关接口/代码测试}
文章目录 1.初识共享内存1.0浅谈System V1.1什么是共享内存?1.2Linux-System V共享内存1.3图解共享内存1.4对共享内存的理解 2.创建共享内存2.1共享内存如何创建?2.2代码运行与测试2.3shm与pipe的区别2.4shm缺乏访问控制 3.代码理解shm3.1Log.hpp3.2comm…...
Web渗透测试流程
什么是渗透测试 渗透测试 (penetration test),是通过模拟恶意黑客的攻击方法,来评估计算机网络系统安全的一种评估方法。这个过程包括对系统的任何弱点、技术缺陷或漏洞的主动分析,这个分析是从一个攻击者可能存在的位置来进行的,并且从这个…...
探索机器学习的无限可能性:从初学者到专家的旅程
探索机器学习的无限可能性:从初学者到专家的旅程 在当今数字时代,机器学习无疑是最引人注目的技术之一。它已经深入到我们生活的方方面面,从个性化推荐到自动驾驶汽车,再到医疗诊断和金融预测。但是,即使我们已经见证…...
【python】六个常见爬虫案例【附源码】
大家好,我是博主英杰,整理了几个常见的爬虫案例,分享给大家,适合小白学习 一、爬取豆瓣电影排行榜Top250存储到Excel文件 近年来,Python在数据爬取和处理方面的应用越来越广泛。本文将介绍一个基于Python的爬虫程序&a…...
Java零基础-多维数组
哈喽,各位小伙伴们,你们好呀,我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。 我是一名后…...
Linux网络套接字之UDP网络程序
(。・∀・)ノ゙嗨!你好这里是ky233的主页:这里是ky233的主页,欢迎光临~https://blog.csdn.net/ky233?typeblog 点个关注不迷路⌯▾⌯ 实现一个简单的对话发消息的功能! 目录…...
Apache POI 解析和处理Excel
摘要:由于开发需要批量导入Excel中的数据,使用了Apache POI库,记录下使用过程 1. 背景 Java 中操作 Excel 文件的库常用的有Apache POI 和阿里巴巴的 EasyExcel 。Apache POI 是一个功能比较全面的 Java 库,适合处理复杂的 Offi…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
