当前位置: 首页 > news >正文

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修饰指针变量的时候

  1. const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来修改,但是指针变量本身的内容是可以修改的。

  2. 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 什么叫野指针&#xff1f;4. 1 野指针的成因4.1.1 指…...

十七、openCV教程 图像轮廓

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

基于视觉的语义匹配见多了,那基于雷达的呢?

论文题目&#xff1a; LiDAR-based HD Map Localization using Semantic Generalized ICP with Road Marking Detection 论文作者&#xff1a; Yansong Gong, Xinglian Zhang, Jingyi Feng, Xiao He and Dan Zhang 作者单位&#xff1a;北京驭势科技有限公司 导读&#xff…...

01、爬虫学习入门

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

我与C语言二周目邂逅vlog——6.文件操作

1. 为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失 了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久…...

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代理是网络中常见的一种工具&#xff0c;可以帮助我们提升网络安全性和隐私保护&#xff0c;优化网络访问速度。本文将详细介绍什么是HTTP代理及其适用的场景。 HTTP代理是介于客户端&#xff08;如浏览器&#xff09;和服务器之间的中间服务器。它接收客户端的HTTP请求&a…...

电动汽车充电技术及运营知识问答pdf

电动汽车充电技术及运营知识问答 作者:马银山编著 出版社:北京&#xff1a;中国电力出版社 ISBN:9787512320406 资源大小:16.99MB 目录&#xff1a; http://literalink.top/resource/detail/7181601144102195200 第一章 电动汽车基本知识 1 1-1什么是电动汽车&#xff1f; 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 啥意思&#xff1f;3. git log 最主要功能是什么&#xff1f;4. git log <commit1>..<commit2> 什么意思5. 查看最近n次commit6. References 1. 查询 git log 的文档 git help log --web市面上针对 git …...

Win10出现错误代码0x80004005 一键修复指南

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

C++ 基础(类和对象下)

目录 一. 再探构造函数 1.1. 初始化列表&#xff08;尽量使用列表初始化&#xff09; 二. static成员 2.1static成员初始化 三.友元 3.1友元&#xff1a;提供了⼀种 突破类访问限定符封装的方式. 四.内部类 4.1如果⼀个类定义在另⼀个类的内部&#xff0c;这个内部类就叫…...

java RestClientBuilder es 集群 鉴权

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

【OpenCV】中saturate_cast<uchar>的含义和用法是什么?

saturate_cast<uchar>主要是为了防止颜色溢出操作&#xff08;0~255&#xff09; if(data<0) data0; elseif(data>255) data255;...

【数据结构】哈希表二叉搜索树详解

&#x1f48e; 欢迎大家互三&#xff1a;2的n次方_ &#x1f48e;所属专栏&#xff1a;数据结构与算法学习 &#x1f341;1. 二叉搜索树 二叉搜索树也称为二叉查找树或二叉排序树&#xff0c;是一种特殊的二叉树结构&#xff0c;它的特点是&#xff1a; 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库中的一个函数&#xff0c;用于对图像进行归一化处理。归一化是一种线性变换&#xff0c;可以将图像像素值的范围缩放到指定的区间。这种操作在图像处理中非常有用&#xff0c;特别是在需要将图像数据用于某些…...

LINUX操作系统安全

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

vue3.0学习笔记(三)——计算属性、监听器、ref属性、组件通信

1. computed 函数 定义计算属性&#xff1a; computed 函数&#xff0c;是用来定义计算属性的&#xff0c;计算属性不能修改。 计算属性应该是只读的&#xff0c;特殊情况可以配置 get set 核心步骤&#xff1a; 导入 computed 函数 执行函数 在回调参数中 return 基于响应…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...