c语言指针2
文章目录
- 一、void * 指针
- 二、const关键字
- 1.const修饰变量
- 2.const修饰指针变量
- 2. 1 const放在*的右边
- 2. 2 const放在*的左边
- 2. 3 总结
- 三、指针的运算
- 3. 1指针的加减运算
- 3. 2 指针 - 指针
- 3. 3 指针的关系运算
- 四、野指针
- 4. 1 什么叫野指针?
- 4. 1 野指针的成因
- 4.1.1 指针未初始化
- 4.1.2 指针越界访问
- 4.1.3 指针所指向的那块空间释放
提示:以下是本篇文章正文内容,下面案例可供参考
一、void * 指针
在c与语言中,指针的类型有很多:
指针类型 | 指向 | 解引用 |
---|---|---|
char* | 指向字符的指针 | 解引用访问1个字节 |
short* | 指向短整型的指针 | 解引用访问2个字节 |
int* | 指向整型的指针 | 解引用访问4个字节 |
float* | 指向单精度浮点型的指针 | 解引用访问4个字节 |
特例
但是除去上面常见的一些类型,c语言中还有一个特别的指针类型叫做void * 指针类型
。
void*特点1
void*指针也称无具体类型的指针,代表这个指针是没有具体类型的。也就是它可以接收任意类型的指针。在下面图中,我们可以看到,用void*指针可以接收任意类型的指针。
在这里有的读者可以会很疑惑,我知道这个数据是什么类型的,直接用这个类型不就可以了,为啥还要单独弄出来一个void*的指针类型。在这里这里每个类型的数据都是直接给出来的,但是以后我们想要写一个函数,函数接收的数据类型是不可知的,我们总不能把所有数据类型都写在函数的参数中,于是我们用void*指针进行接收所有类型的指针就可以,这样既不会出错误,也不会出现多参数的情况。
void*特点2
void*指针也存在一些小问题,就是void\*指针不能进行指针的加减操作和解引用操作
。这是因为void*指针是无具体类型的指针,你要对它进行解引用或者指针的加减,它访问不知道是几个字节。所以不能对void*类型的指针进行这些运算。
二、const关键字
在c语言中还有一个关键字叫const,const英文意思叫常数,所以在c语言中,const的作用就是给予变量常属性,使得被const修饰的变量无法修改。
1.const修饰变量
在这里可以看到const修饰变量,变量具有常属性,此时变量不可以被修改,而没有被const修饰的变量a此时可以被修改。b被const修饰,b此时具有常属性,b不可以被修改,但是b可不是常量,下面我们来验证一下。
定义数组我们只能用常量来定义数组的元素个数,上图显而易见,我们用const修饰变量b,b并不是变成常量了,它只是具有了常属性,不能被修改,所以被const修饰的变量我们也称常变量。
2.const修饰指针变量
在了解const修饰指针变量,我们先了解一下为什么要修饰指针变量,我直接修饰变量不就不能改变值了么?听我细细道来:
在这里我们虽然用const修饰变量b,b不能被修改,但是我们可以通过地址去修改它,这就好比法律,总是存在一些漏洞,这就需要进行修改和矫正,于是就需要const修饰指针变量。const修饰指针变量可以放在两个地方,一个是放在*的左边,一个是放在*的右边。
2. 1 const放在*的右边
int main()
{int b = 10;int a = 20;int* const p = &b;*p = 20;//p = &a; //errprintf("%d",b);return 0;
}
在这里运行代码后我们可以发现const放在*右边修饰的指针变量p,const修饰指针变量p,此时存放在指变量p中的值不可改变,但是指针变量p所指向的那块空间可以改变。
2. 2 const放在*的左边
int main()
{int b = 10;int a = 20;int const* p = &b;*p = 20; //errp = &a; printf("%d",b);return 0;
}
在这里运行代码可以看出来,此时const放在*的左边,const修饰的指针变量的指向,此时通过指针变量p指向去修改b中的值是不可以的,但是可以修改指针变量p中存放的地址。
2. 3 总结
const修饰指针变量的时候
-
const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来修改,但是指针变量本身的内容是可以修改的。
-
const如果放在* 的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针所指向的内容,是可以通过指针进行修改的。
三、指针的运算
了解完指针概念之后,我们接下来要熟悉指针在使用过程中是如何运算的,指针的运算主要有三种:指针的加减运算,指针减去指针,指针的关系运算。
3. 1指针的加减运算
指针的加减运算主要用于数组方面,在数组中,内存是连续存放的,知道首元素的地址可以顺藤摸瓜的找到后面的元素。
定义一个整型数组
int arr[5] = { 1,2,3,4,5 };
数组在内存中存放如下
在代码中的运用
int main()
{int arr[5] = { 1,2,3,4,5 };//打印数组内的元素int* p = &arr[0];int i = 0;for (i = 0; i < 5; i++){printf("%d ", *(p+i));}return 0;
}
分析
在这里我们首先定义了一个数组arr里面存放5个元素,然后我们取出首元素的地址放入p中,此时循环打印,我们通过解引用p可以访问首元素,p+1此时访问的是下一个元素的地址。对应i,当i=0的时候,访问数组中的第一个元素,以此类推,当i=4的时候,访问的是数组的最后一个元素。
3. 2 指针 - 指针
指针减去指针得到的是两个指针之间元素的个数
通过指针减去指针的方式实现strlen函数
strlen是一个统计字符个数的函数,它的结束条件是碰到\0停止,得到的是\0之前的元素的个数
char str[] = "abcdef"
数组在内存中存放如下
思路
在这里我们想要实现strlen的自我实现,并且运用指针减去指针的原理 ,因为数组传参传进来的就是首元素的地址,我们得先定义一个起始指针变量start用来存放首元素的地址,然后我们让地址进行一步一步加1,地址每次加一访问的都是下一个元素的地址,我们只需要判断该元素是不是\0如果是的话就停止指针加减操作,用结束的指针地址,减去起始指针的地址,就可以得到字符串的字符的个数了。
代码实现
int my_strlen(char* str)
{char* start = str;while (*str != '\0'){str++;}return str - start;
}
int main()
{char str[] = "abcdef"; int ret = my_strlen(str); printf("%d", ret); return 0;
}
3. 3 指针的关系运算
上节内容我们讲解了有关于内存的知识,在计算机中,计算机将内存划分为一个一个的内存单元,一个内存单元占一个字节,每个内存单元都有它相应的地址。在内存中也存在高地址和低地址。在数组中,曾经就对数组在内存中的存储进行测试过,数组在内存中的存储是由低地址到高地址方向连续存储的。
定义一个数组
定义一个数组,打开调试窗口中的内存窗口,找到数组arr在内存中的存储,这里我们可以发现每个整型数组元素占四个字节,每个字节都有自己的内存地址。
利用指针的关系运算打印出整型数组中的全部元素
#include <stdio.h>
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]); while(p<arr+sz) //指针的⼤⼩⽐较 {printf("%d ", *p); p++; }return 0;
}
分析
在上面代码中,我们首先定义了一个数组arr存放1到10这10个整数,然后我们取出数组首元素的地址,因为数组在内存中是从低地址向高地址进行存放的,如上面的代码调试内存窗口可以看出,1的存放地址是最低的,10的存放地址是最高的。取出完地址放入指针变量p中后,我们让p与数组首元素地址加9进行相比(等价于第十个元素的地址),首元素地址小于最后一个元素的地址进入循环,首先通过指针变量p所指向的那份空间打印首元素,然后指针变量+1,再与最后一个元素的地址进行相比,依次直到指针变量p的地址大于等于最后一个元素的地址时,打印结束。
四、野指针
4. 1 什么叫野指针?
野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)。
接下来我们用一张图来解释一下什么叫野指针
这是一条狗,假如它有主人的,那么他就指向了它的主人,他的任何事情都由主人进行处理;假如他没有主人,那么他就是一条野狗,野狗是没有指向的,他会四处乱串,所以他的位置也是不可知的,同时他也是非常危险的,他没有接收训话,人一旦靠近它很可能就会被咬伤。在这里野狗就等同于野指针,野指针指向位置是不可知的,同时也是非常危险的,在指针中出现野指针会导致代码严重的后果。
4. 1 野指针的成因
4.1.1 指针未初始化
#include <stdio.h>
int main()
{ int *p;//局部变量指针未初始化,默认为随机值*p = 20;return 0;
}
分析
在这里指针定义并没有给指针进行初始化,在定义变量中,变量未进行初始化默认的是随机值,指针变量同样如此,指针变量未进行初始化,指针变量存的就是随机地址,此时通过指针变量去访问该地址中的值进行修改值是没有权限的。这个就好比你在某地订了个酒店,你朋友想去找你,但是他不知道哪个是你地址,他就随机找一个地址就想直接闯进去,这肯定不行的。在这里也是同样的道理,指针未初始化,给定的是随机地址,随机地址就是没有没有规定指向的,此时指针变量p就是野指针。
4.1.2 指针越界访问
#include <stdio.h>
int main()
{int arr[10] = {0};int *p = &arr[0];int i = 0;for(i=0; i<=11; i++){//当指针指向的范围超出数组arr的范围时,p就是野指针*(p++) = i;}return 0;
}
分析
在这里,我们定义了10个数组,通过指针访问却越界访问到了第十一个地址空间,此时当指针指向的范围超出数组的范围的时候,指针变量p就是野指针。野指针的指向是随机的,通过它访问的值是随机的,他可能是任何一个值。
4.1.3 指针所指向的那块空间释放
#include <stdio.h>
int* test()
{int n = 100;return &n;
}
int main()
{int*p = test();printf("%d\n", *p);return 0;
}
分析
上述代码我们调用test函数,test函数返回n的地址用指针变量p进行接收,test函数调用完后,n变量所开辟的空间就还给系统空间了,此时我们在主函数通过指针变量p去访问那块空间是没有访问权限的,所以此时代码是存在错误的。而指针变量p就是野指针。
相关文章:

c语言指针2
文章目录 一、void * 指针二、const关键字1.const修饰变量2.const修饰指针变量2. 1 const放在*的右边2. 2 const放在*的左边2. 3 总结 三、指针的运算3. 1指针的加减运算3. 2 指针 - 指针3. 3 指针的关系运算 四、野指针4. 1 什么叫野指针?4. 1 野指针的成因4.1.1 指…...

十七、openCV教程 图像轮廓
一、图像轮廓 图像轮廓是具有相同颜色或灰度的连续点的曲线.轮廓在形状分析和物体的检测和识别中很有用。 轮廓的作用:.用于图形分析、物体的识别和检测 注意点: 为了检测的准确性,需要先对图像进行二值化或Canny操作。 画轮廓时会修改输入的图像,如…...

基于视觉的语义匹配见多了,那基于雷达的呢?
论文题目: LiDAR-based HD Map Localization using Semantic Generalized ICP with Road Marking Detection 论文作者: Yansong Gong, Xinglian Zhang, Jingyi Feng, Xiao He and Dan Zhang 作者单位:北京驭势科技有限公司 导读ÿ…...

01、爬虫学习入门
爬虫:通过编写程序,来获取获取互联网上的资源 需求:用程序模拟浏览器,输入一个网址,从该网址获取到资源或内容 一、入门程序 #使用urlopen来进行爬取 from urllib.request import urlopen url "http://www.ba…...

我与C语言二周目邂逅vlog——6.文件操作
1. 为什么使⽤⽂件? 如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失 了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久…...

Hugo 部署与自动更新(Git)
文章目录 Nginx部署Hugonginx.confhugo.conf Hugo自动更新Hugo自动更新流程添加访问令牌添加web hookrust实现自动更新接口 Nginx部署Hugo nginx.conf user nginx; worker_processes auto;error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;even…...

HTTP代理揭秘:这些场景你都用对了吗?
HTTP代理是网络中常见的一种工具,可以帮助我们提升网络安全性和隐私保护,优化网络访问速度。本文将详细介绍什么是HTTP代理及其适用的场景。 HTTP代理是介于客户端(如浏览器)和服务器之间的中间服务器。它接收客户端的HTTP请求&a…...

电动汽车充电技术及运营知识问答pdf
电动汽车充电技术及运营知识问答 作者:马银山编著 出版社:北京:中国电力出版社 ISBN:9787512320406 资源大小:16.99MB 目录: http://literalink.top/resource/detail/7181601144102195200 第一章 电动汽车基本知识 1 1-1什么是电动汽车? 11-…...

playbooks 分布式部署 LNMP
1、环境配置 ansible 服务器 192.168.10.10nginx 服务器 192.168.10.20mysql 服务器 192.168.10.21php 服务器 192.168.10.22 2、安装 ansble #192.168.10.10节点 yum install -y epel-release #先安装 epel 源 yum install -y ansible配置主机清单 …...

成为git砖家(8): 使用 git log 查询范围内的 commit
文章目录 1. 查询 git log 的文档2. 不带任何参数: git log 啥意思?3. git log 最主要功能是什么?4. git log <commit1>..<commit2> 什么意思5. 查看最近n次commit6. References 1. 查询 git log 的文档 git help log --web市面上针对 git …...

Win10出现错误代码0x80004005 一键修复指南
对于 Windows 10 用户来说,错误代码 0x80004005 就是这样一种迷雾,它可能在不经意间出现,阻碍我们顺畅地使用电脑。这个错误通常与组件或元素的缺失有关,它可能源自注册表的错误、系统文件的损坏,或者是软件的不兼容。…...

C++ 基础(类和对象下)
目录 一. 再探构造函数 1.1. 初始化列表(尽量使用列表初始化) 二. static成员 2.1static成员初始化 三.友元 3.1友元:提供了⼀种 突破类访问限定符封装的方式. 四.内部类 4.1如果⼀个类定义在另⼀个类的内部,这个内部类就叫…...

java RestClientBuilder es 集群 鉴权
在Java中使用RestClientBuilder连接到Elasticsearch集群并进行鉴权,可以通过设置HttpHosts、RequestConfig以及添加相应的Header来实现。 以下是一个示例代码: import org.apache.http.Header; import org.apache.http.HttpHost; import org.apache.htt…...

【OpenCV】中saturate_cast<uchar>的含义和用法是什么?
saturate_cast<uchar>主要是为了防止颜色溢出操作(0~255) if(data<0) data0; elseif(data>255) data255;...

【数据结构】哈希表二叉搜索树详解
💎 欢迎大家互三:2的n次方_ 💎所属专栏:数据结构与算法学习 🍁1. 二叉搜索树 二叉搜索树也称为二叉查找树或二叉排序树,是一种特殊的二叉树结构,它的特点是: 1. 若左树不为空&am…...

【SpringBoot】参数传递之@ModelAttribute
ModelAttribute标注的方法会在Controller类的每个映射URL的控制执行方法之前执行。 ModelAttribute public void findUserById(PathVariable("userId") Long userId,Model model){ model.addAttribute("user",userService.findUserById(userId)); } GetM…...

frp搭建ssh内网穿透
frp软件包下载 检查外网服务器架构 uname -i官网下载对应的版本 https://github.com/fatedier/frp/releases 使用wget或拷贝文件到外网服务器/opt目录下并解压 解压得到frp_0.59.0_linux_amd64文件夹 tar -zxvf frp_0.59.0_linux_amd64.tar.gzfrpc 这是 frp 的客户端可执…...

OpenCV库学习之cv2.normalize函数
OpenCV库学习之cv2.normalize函数 一、简介 cv2.normalize是OpenCV库中的一个函数,用于对图像进行归一化处理。归一化是一种线性变换,可以将图像像素值的范围缩放到指定的区间。这种操作在图像处理中非常有用,特别是在需要将图像数据用于某些…...

LINUX操作系统安全
一、概述内容 操作系统负责计算机系统的资产管理,支撑和控制各种应用程序运行,为用户提供管理计算机系统管理接口。操作系统也是构成网络信息系统的核心关键组件,其安全可靠性决定了计算机系统的安全性和可靠性。 操作系统安全是指满足安全…...

vue3.0学习笔记(三)——计算属性、监听器、ref属性、组件通信
1. computed 函数 定义计算属性: computed 函数,是用来定义计算属性的,计算属性不能修改。 计算属性应该是只读的,特殊情况可以配置 get set 核心步骤: 导入 computed 函数 执行函数 在回调参数中 return 基于响应…...

Elasticsearch面试三道题
针对Elasticsearch的面试题,从简单到困难,我可以给出以下三道题目: 1. Elasticsearch的基本概念与优势 问题:请简要介绍Elasticsearch是什么,并说明它相比传统数据库的优势有哪些? 答案: El…...

大厂面经:大疆嵌入式面试题及参考答案(4万字长文:持续更新)
目录 Linux 系统调用的过程,中间发生了什么? 表格总结 Linux 中断流程,谈谈你对中断上下文的理解 中断流程 中断上下文理解 Linux schedule() 函数的原理和调用的时机 schedule() 函数原理 调用时机 页表实现机制,分页的缺点? 页表机制 分页的缺点 介绍操作系…...

数据结构【有头双向链表】
目录 实现双向链表 双向链表数据 创建双向链表 初始化双向链表创建(哨兵位) 尾插 打印双向链表 头插 布尔类型 尾删 头删 查询 指定位置后插入 指定位置删除数据 销毁 顺序表和链表的分析 代码 list.h list.c test.c 注意:…...

docker 安装jenkins详细步骤教程
Jenkins 是一个开源的持续集成(CI)和持续部署(CD)工具,用于自动化软件开发过程中的构建、测试和部署。 特点和功能: 持续集成:Jenkins 可以自动触发构建过程,检查代码变更并进行构建、测试和部署,以确保团队的代码始终保持可集成状态。 插件生态系统:Jenkins 拥有丰富…...

C++模板函数
C模板函数 函数模板简单的函数模板模板类型推导返回输入的类型,模板返回的类型由输入的决定返回类型的模板参数返回值使用auto,编译器自动推导 默认模板实参模板参数重载函数模板 constexpr关键字 函数模板 简单的函数模板 typename 可以使用class代替…...

c#中的正则表达式和日期的使用(超全)
在 C# 中,正则表达式(Regular Expressions)是一种强大的文本处理工具,用于执行各种字符串搜索、替换和验证任务。以下是一些常用的正则表达式示例及其用途: 1. 邮箱地址验证 string emailPattern "^[^\s][^…...

论文阅读【检测】:商汤 ICLR2021 | Deformable DETR
文章目录 论文地址AbstractMotivation技术细节多尺度backbone特征MSDeformAttention 小结 论文地址 Deformable DETR 推荐视频:bilibili Abstract DETR消除对目标检测中许多手工设计的组件的需求,同时表现出良好的性能。然而,由于Transfor…...

dpdk发送udp报文
dpdk接收到udp报文后,自己构造一个udp报文,将收到的报文中的源mac,目的mac,源ip,目的ip,源端口和目的端口交换下顺序填充到新的udp报文中,报文中的负载数据和收到的udp保持一致。 注࿱…...

网站后端管理和构建java项目的工具-Maven
maven是用于管理和构建java项目的工具。 管理Jar包 无论是使用eclipse、IDEA创建的maven项目,格式都是统一的。 不同开发工具创建的maven项目兼容。 test是对main测试的代码。main中的resources中放置配置文件。 对于Maven,一个Maven项目就是一个对象…...

深入理解计算机系统 CSAPP 家庭作业11.10
A: //home.html <form action"/cgi-bin/adder" method"GET"><ul><li><label for"n1">n1:</label><input type"text" id"n1" name"n1" /> //name的值决定页面提交后…...