带你学C语言~指针(1)

news2024/11/14 20:33:32

        Hello,CSDN的各位家人们,你们好啊!今天,小赵要给大家分享的C语言知识是指针,相信不少家人们都或多或少被指针搞得晕头转向,小赵一开始也是,但后来小赵经过不断地努力学习,终于将这里面的知识弄懂了。由于指针的知识点实在太多,小赵决定将它分为几个小部分,让大家更好地学习和吸收。

目录

🎾内存与地址

⚾内存

⚾地址

🎾指针变量与地址

⚾取地址

⚾指针变量

⚾如何认识指针类型

⚾解指针

⚾指针占多少内存

🥉指针变量类型的意义

🎯不同指针类型的影响

🎯void型指针

🎯const修饰指针

🥈指针运算

🏉指针与整数运算(加减)

🏉指针与指针运算

🏉指针的大小比较

🥇野指针

🏓野指针是什么

🏓如何避免野指针

🏐assert断言

🏆指针的使用和地址的调用

⚽模拟strlen函数

⚽传值与传址

🏆结束语


     

🎾内存与地址

⚾内存

在开始指针之前,小赵先和你们聊聊内存,内存是什么,其实我们大多数人心中应该是有自己的一个定义的,因为我们的手机啊,电脑啊,存储一些软件,音乐什么的靠的其实就是我们的内存,可内存究竟是怎么调用的,我们好像并不太清楚也并不太了解。但我们的生活中有一个有意思的例子可以让我们摸清楚就是,我们的房子也是用来存东西的,存我们的书籍,衣服等等,那它是怎么调用和找到的,其实靠的点就两个一个门牌,一个钥匙。

正是这两个东西的存在,让我们所有人都可以井然有序的生活,不会乱放自己的东西在别人家,不会走错门,也让自己的东西不会被别人偷。那我们的内存是不是也是一样呢。其实电脑和内存的关系就是下面这张图展现的。

我们的电脑其实就是通过给每个内存编号,来进行存储访问的,而这个编号其实就是我们下面要讲的地址了。 

⚾地址

如此庞大的内存,究竟是靠着怎么编写的地址来进行有序的访问,相信这是不少小伙伴们的疑惑,其实要解决这个问题还是要借助我们的内存。我们都知道,我们的内存存储是分很多的单位。正如下面这张图。

 在这些茫茫的内存中我们的地址选择了字节,内存把自己分成了无数个细小的字节单位,给每一个字节编写编号,而这个编号就是我们的地址。

🎾指针变量与地址

⚾取地址

我们说既然每个东西它都有自己的内存也都有自己的地址,那我们如何去取出我们的地址呢?又该如何去看到我们的地址。那么小赵就在这里为大家演示一下,首先呢,在我们的C语言中是有一个专门的操作符用来取这个地址的,这操作符就叫取地址操作符,即&。那么如何用呢?

利用我们VS的调试的功能

 在里面输入我们的地址,然后再按一下回车,就可以出来我们的地址了。

 

⚾指针变量

那么既然已经如此完美了,那为什么还要我们指针的存在呢?就像你要去往任何一个房屋总要直到它的地址,而我们的指针干的就是存地址的活,同时它还可以帮助你去打开地址,往那块内存里面去存。这一点就相当于什么呢,就好比这个房子的主人把自己房子的门牌号告诉给了那个人,同时还给了它钥匙,让他能够去拥有这个房子的使用权,但这个房子其实还是归属于这个房主的,在现实中其实也有对应就是租房子给别人的那种感觉。

⚾如何认识指针类型

讲到现在也没把指针长啥样,拉出来给大家看看,那么现在我们就当当当请出我们的指针,来看看这究竟长啥样,能如此强大。

其实看完了这个图相必大家也能推出其他类型的指针,比如字符指针,short类型的指针,long.....等一系列指针,但其实指针也有一些需要注意的或者说难写的,这个我们后面再聊。

⚾解指针

那好了,现在指针我们拿到了地址了,可你不能光给我地址啊,我都租了,你好歹让我在你这个房子里倒腾一下,这个我们C语言也早就准备好了,我们C语言的解指针用的就是*,对没错这个是不是超级像你那个钥匙插进去的那个门缝,所以这个可好记了,下面小赵就要给大家演示一下我们该怎么用这个指针去倒腾这个房子了。

怎么样是不是很神奇,其实这里小赵还有一个比较有意思的说法,a=10,其实就相当于我们家本来的样子,*p=150,就相当于我们打开家,把家倒腾成的样子,然后我们再输出家的样子。怎么样还是有意思的吧。

⚾指针占多少内存

那么我们的指针究竟占多少的内存呢?

这个其实这要分情况的,首先就是我们x64(即64位)的版本下面,我们可以打出来看看。

接着就是我们的x86(即32位)

🥉指针变量类型的意义

相信这个时候就有人问了,指针变量所占的内存的大小是一样的吗?那当然是一样的。那为什么还要划分为各种指针类型呢?既然大家内存都一样,直接用就好了,分这么多类干嘛?那么接下来小赵就来帮助你去解决这个问题。

🎯不同指针类型的影响

其实我们都知道,不同的类型所占的内存大小是不一样的,而到了指针这里,就完全可以看作是它所控制的内存大小,比如你租房子只租给一个人卧室,那么对这个人来说他所能改变的其实就只能是这个卧室以内的范围,外面的厨房其实他没办法去改变。那么对指针来讲也是一样的。比如你一个指向char类型的指针去指向人家int的类型的指针那你所能改变的也只有人家的四分之一部分咯。

在上面的这些案例中,我们不难发现不同类型的指针变量所拥有的权利是不一样的,它们的访问权完全由自身所指向的类型的所占的内存大小决定。

🎯void型指针

但一个队伍总会有这么一个特殊的存在,也可以说是几乎全能的存在,没错这个在指针中可以访问一切类型的指针类型是存在的就是我们的void型指针,这个指针类型可以接收所有的指针类型,但全能未必是好事,它的遗憾就是它无法打开门读取(即无法解指针),也无法对内存做出任何修改。如果要进入其中修改,就必须强制类型转化成其他类型,这个我们后边会多次使用这个指针去接收一些其他指针,在这里小赵就不多讲了,就给大家举个简单的例子吧。

🎯const修饰指针

首先我们先再一次认识一下我们const.

const 限定符,它把一个对象转换成一个常量。

既然const是把我们修饰的变量转变为常量,那你说这个变量还能变吗?当然是不能啦。比如我们的常量1,还能有一天忽然变了不成,当然不可能变啦。下面可以看一下小赵举得一个例子更加深刻地体会一下。 

那放到我们的指针上又是怎么样呢?

先看第一种

那么这里为什么会报错呢,其实这里就相当于是修饰我们指针变量所指的地址的那部分内存,就是我把你这部分内存给定下来了,既然定下来了,那你说这个内存我还能变吗?

但是我们p这个租房子的是可以走的,你定了房子的样子,但不代表我这个租房子的人不能走啊。

我们的p只需要重新去租个房子就好了。

下面看第二种

其实这里也相当于我们的第一种,当然小赵在这里有个比较有意思的说法啊就是把这个*p(人和钥匙绑一起就是那个房间)当成我们租的那块地盘,你把我租的地盘定下了,那你说这个地盘还能动吗?而单独的一个P则相当于一个自由自在的人,那它不就可以改变了吗?

接下来看第三种。

第三种其实你再用小赵上面的理解就好理解了,就是我把你这个租客定下来,也就是这个指针变量所指的地址定下来,那你说他还自由吗,他不久不能换地址了,但这时候地址那块空间没定下来,那不就可以随便改吗?

总结:

结论:const修饰指针变量的时候
• const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。
但是指针变量本身的内容可变。
• const如果放在*的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指 向的内容,可以通过指针改变。

🥈指针运算

那么接下来就有人要问了,指针可以运算吗,运算的意义又是什么呢?

下面小赵来为你解答。

🏉指针与整数运算(加减)

指针于整数的与运算,上面我们提到了,我们地址在内存中是以一个一个的单元存储的,每个单元是1个字节,那我们的指针与整数的加减运算,其实就是跳过了多少个这样的单元,而跳过多少个单元的问题,那究竟跳过多少个呢?其实就是(整数)*(指向的类型所占的字节大小)

这里小赵为了方便大家理解,用我们的数组做个示范。因为数组里面存储的数据是连续的。

🏉指针与指针运算

那么指针与指针的运算,这个就比较有意思了,它的结果其实就是这两个地址之间的元素多少,当然这个其实我们一般也是数组用的多,因为其他的数据都不一定是连续的,只有数组我们目前确定是连续的。

🏉指针的大小比较

那么两个指针的大小比较呢,其实这个就跟我们的地址高低有关了,其实也是后面小赵要与各位聊的,但可以透露的一点是数组下面的下标越高,它的地址一般越高,毕竟也是后创建的。

当然还有一点要提的是,我们的数组必须是在一个数组中,两个数组是不连续的。 

🥇野指针

🏓野指针是什么

野指针往往其实指的就是一块没有被开发的内存,就是你这个指针啊,没有指向任何地址,这个地址就是随机的,同时也是不允许被使用的。就像你随便找了一个房子没被人授权,这能允许吗?

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)指针变量在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的。 

像我们在敲代码时候常遇到的情况有 三种

第一种,是由于我们没给它地址。

这时候我们的编译器是会报错的;

第二种越界访问。

这里我们跳过了a这块区域,然后就是未知区域,所以出来的也是随机值。 

第三种使用的空间被回收或释放

这里出现的情况就是我们的函数在运行结束后将自己开辟的那块空间收回了,所以再找也就是一块野指针了。(这里函数栈帧会讲)

🏓如何避免野指针

那么如何避免这个野指针呢?

方案一

我们把我们的指针上来就指向一个明确的地址。

方案二

给它一个空指针,让它什么都没有无法使用。

它既然是一块空区域,那你也就没办法塞东西给里面了。

🏐assert断言

assert是用来干嘛呢?我们可以先用小赵上次说的网站查查。

我们注意到assert是看你括号里面的东西是否是真的,如果错了它就会终止程序的运行。

那么这个就刚好可以判断我们的指针是否是空指针,防止我们的错误使用。

🏆指针的使用和地址的调用

好了,我们了解上面的一些关于指针的相关知识下面小赵带你去实际应用我们的指针吧。

⚽模拟strlen函数

 其实这个函数也是小赵多次提到的一个函数,它的主要作用,就是去算一个字符串在\0之前的字母数,同时还要注意的一点是它的是要头文件的即#include<string.h>

 那我们究竟该如何实现呢?在这里小赵就不卖关子了。

int my_strlen(char* a)
{
	int count = 0;
	while (*a != '\0')//*a不等于'\0',继续运行
	{
		a++;//看下一个字母
		count++;//统计字母数量
	}
	return count;//返回字母数量
}
int main()
{
	char a[10] = "abcdef";
	int m = my_strlen(a);
	printf("%d", m);

}

 

⚽传值与传址

其实之前学完函数后就有不少人有这样的困惑了,就是要给两个变量在函数里面换值的无法成功,这其实是因为函数里面创建的变量都是临时变量,当函数运行完了,这些代码的空间什么的都会回收,我们的值就像我们输入进去,给它们里面的两个在里面换,但人间不会影响到你外面的人

但如果这里你用我们的地址就不一样了,因为我们如果用地址,那么它就可以开打开我们这边的房间对我们进行换值了。

void Swap(int* px, int* py)//传入的地址给你
{
	int tmp = 0;
	tmp = *px;//这部分和之前的交换一样
	*px = *py;
	*py = tmp;
}
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	printf("交换前:a=%d b=%d\n", a, b);
	Swap(&a, &b);
	printf("交换后:a=%d b=%d\n", a, b);
	return 0;
}

🏆结束语

好了小赵今天的分享就到这里了,如果大家有什么不明白的地方可以在小赵的下方留言哦,同时如果小赵有什么地方说得不对也希望得到大家的指点,谢谢各位家人们的支持。你们的支持是小赵创作的动力,加油。

如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持小赵,如有不足还请指点,小赵及时改正,感谢大家支持!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1315626.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Anaconda】Ubuntu anaconda使用(新建环境、最小化安装Tensorflow, CUDA对应关系)

Ubuntu anaconda使用&#xff08;新建环境、最小化安装Tensorflow&#xff09; 文章目录 Ubuntu anaconda使用&#xff08;新建环境、最小化安装Tensorflow&#xff09;使用conda打包虚拟环境查看已创建的环境删除虚拟环境命令下运行.ipynb文件 清华源地址&#xff1a; https:…

Postman中参数填写方式

Postman中参数填写和请求方法有关&#xff0c;一般接口用例请求方法GET与POST常用&#xff0c;所以主要是这两种请求方法请求参数填写 一、GET请求方法参数填写 1、直接在URL中填写请求参数,如直接在URL中填写&#xff1a; http://www.example.com:8089/userapi?unamelisi&…

Java医院3D人体智能导诊系统源码 Uniapp+springboot 微信小程序

“智能导诊”以人工智能手段为依托&#xff0c;为人们提供智能分诊、问病信息等服务&#xff0c;在一定程度上满足了人们自我健康管理、精准挂号等需求。智能导诊可根据描述的部位和病症&#xff0c;给出适合病症的科室参考。 智能导诊页面会显示男性或女性的身体结构图&#x…

Python读写arxml文件

文章目录 前言一、XML简介二、XML文件结构三、Python读取xml文件安装ElementTree库读取xml文件四、Python写入xml文件前言 本文主要通过介绍arxml文件,为后续python脚本开发奠定基础。 arxml是AUTOSAR XML的简称,是一个通用的配置/数据库文件,实质是一个xml文件。 ①更规范…

机械设备企业网站建设的效果如何

机械设备涵盖的类目比较广&#xff0c;其市场需求也是稳增不减&#xff0c;也因此无论大小企业都有增长的机会&#xff0c;当然这也需要靠谱的工具及正确的决策。 对机械设备企业来说&#xff0c;产品品质自然是首位&#xff0c;而向外打造品牌、扩展信息及拓客转化自然也是非…

HTML5+CSS3+JS小实例:自适应瀑布流布局

实例:自适应瀑布流布局 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content=&quo…

深入学习《大学计算机》系列之第1章 1.2节——问题描述与抽象

一.欢迎来到我的酒馆 第1章 1.2节&#xff0c;问题描述与抽象。 目录 一.欢迎来到我的酒馆二.问题描述、抽象与建模1.什么是抽象2.为什么要抽象3.什么是建模4.建什么模 三.面向计算机的问题分析四.总结 二.问题描述、抽象与建模 什么是抽象&#xff1f;为什么要抽象&#xff1f…

用EnumSet代替位域

在Java中&#xff0c;可以使用EnumSet来代替位域&#xff0c;以提高代码的可读性和类型安全性。下面是一个简单的例子&#xff0c;演示如何使用EnumSet来管理一组枚举值&#xff1a; import java.util.EnumSet;// 定义一个枚举类型表示权限 enum Permission {READ, WRITE, EXE…

利用canvas封装录像时间轴拖动(uniapp),封装上传uniapp插件市场

gitee项目地址,项目是一个空项目,其中包含了封装的插件,自己阅读,由于利用了canvas所以在使用中暂不支持.nvue,待优化; 项目也是借鉴了github上的一个项目,timeline-canvas,​​​​​​​ ​​​​​​​

【Hive】【Hadoop】工作中常操作的笔记-随时添加

文章目录 1、Hive 复制一个表:2、字段级操作3、hdfs 文件统计 1、Hive 复制一个表: 直接Copy文件 create table new_table like table_name;hdfs dfs -get /apps/hive/warehouse/ods.db/table_nameload data local inpath /路径 into table new_table;修复表&#xff1a; m…

[pasecactf_2019]flask_ssti proc ssti config

其实这个很简单 Linux的/proc/self/学习-CSDN博客 首先ssti 直接fenjing一把锁了 这里被加密后 存储在 config中了 然后我们去config中查看即可 {{config}} 可以获取到flag的值 -M7\x10wd94\x02!-\x0eL\x0c;\x07(DKO\r\x17!2R4\x02\rO\x0bsT#-\x1cZ\x1dG然后就可以写代码解…

数据结构 | 查漏补缺之顺式存储和链式存储、如何评价哈希函数的好坏、链地址法、树的遍历、关键路径、完全图、连通图、迪杰斯特拉、b树

目录 顺式存储和链式存储 优缺点比较 顺序存储 ​编辑 链式存储 如何评价哈希函数的好坏 简述哈希查找中链地址法解决冲突的方法 树的遍历 关键路径 完全图 连通图 迪杰斯特拉 b树 特点&#xff1a; 插入&#xff08;索引不能大于&#xff1a;最大为 M-1 个&#…

单例模式⭐️通过具体代码实现单例模式的不同实现以及周末总结

小伙伴们大家好&#xff0c;又是一个平平淡淡的周末&#xff0c;先来回顾下这周的情况吧 主线开发任务正常&#xff0c;没有滞后首次通过定时任务来处理脚本&#xff0c;测试通过熟悉定时任务的远程&#xff0c;本地来回切换 2023.12.16 天气阴 气温零下 一觉睡…

『App自动化测试之Appium应用篇』| uiautomator + accessibility_id定位方法完全使用攻略

『App自动化测试之Appium应用篇』| uiautomator accessibility_id定位方法完全使用攻略 1 uiautomatorviewer无法连接手机1.1 问题现象1.2 解决方法1.2.1 方法一&#xff1a;使用第三方文件&#xff08;不建议&#xff09;1.2.2 方法二&#xff1a;导入uix和png文件 2 accessi…

Threejs漫天多彩粒子天空--粒子系统打造

一、导语 漫天多彩粒子天空特效应该也是Threejs项目中挺常见的一个需求&#xff0c;因为它是基于粒子系统&#xff0c;可以衍生出许多的不一样的方案&#xff0c;比如&#xff0c;星空特效&#xff0c;下雨特效&#xff0c;飘雪特效等等&#xff0c;不仅可以用在项目中增加氛围…

【Unity 实用工具篇】| 游戏多语言解决方案,官方插件Localization 实现本地化及多种语言切换

前言 【Unity 实用工具篇】| 游戏多语言解决方案&#xff0c;官方插件Localization 实现本地化及多种语言切换一、多语言本地化插件 Localization1.1 介绍1.2 效果展示1.3 使用说明 二、 插件导入并配置2.1 安装 Localization2.2 全局配置 三、多语言映射表3.1 创建多语言文本配…

AWS-CDN只能备用域名访问-使用Lambda@Edge(禁止分配的域名访问)

场景&#xff1a;cdn使用备用域名后&#xff0c;希望用户只能从备用域名访问&#xff0c;而不是自动分配的cdn域名&#xff0c;这也将是一个安全漏洞&#xff0c;被扫描到cdn域名访问刷流量等&#xff01; 【建议部署前查看】参考链接&#xff1a; 1.官方cdn返回示例 2.lambdae…

从菜鸟到专业人士:来自真实 PRD 写作经验的 5 个改变游戏规则的产品管理课程

产品管理是一个复杂且具有挑战性的角色。PRD&#xff08;即产品需求文档&#xff09;就像构建产品的蓝图&#xff0c;可将其视为指导开发团队创造令人惊叹的产品的详细路线图。本文除了介绍产品经理如何写好PRD&#xff0c;也将进一步阐述产品经理应该学习哪些技能&#xff1f;…

【C语言】动态内存管理(C语言的难点与精华,数据结构的前置知识,你真的掌握了吗?)

文章目录 引言一、为什么要动态内存分配二、动态内存分配的相关函数2.1 malloc2.2 free2.3 calloc2.4 realloc 三、常见的动态内存的错误3.1 对NULL指针的解引用3.2 对动态内存越界访问3.3 对非动态内存释放3.4 对动态内存部分释放3.5 对动态内存多次释放3.6 未对动态内存释放&…

DevEco Studio自定义代码颜色

这里以ArkTS代码颜色举例 进入设置&#xff08;快捷键CtrlAltS&#xff09; 选择Editor > Color Scheme > JavaScript 由于之前用习惯VsCode了&#xff0c;这里以注释颜色举例&#xff0c;变为绿色。 上面说的不是以ArkTS代码颜色举例吗&#xff1f;为什么选择JavaScr…