C语言——深入理解指针(1)

目录

1.内存与地址

1.1 什么是内存

1.2 编址

2. 指针的变量和地址

2.1 取地址(&)

2.2 指针变量

2.3 解引用

2.4 指针变量大小

3. 指针变量类型存在的意义

3.1 不同类型指针的解引用

3.2 指针对整数的运算(+,-)

3.3 void* 指针

4. const 修饰

4.1 const 变量

 4.2 const(指针变量)

5. 指针的运算

 6. 野指针

7. assert断言

8.指针的使用和传址调用

举例1:strlen 的模拟实现

传址调用例如:写⼀个函数,交换两个整型变量的值


1.内存与地址

1.1 什么是内存

在这之前我们先说一下生活中的一些与内存非常像的例子

生活中有很多高楼,假设楼里有100个房间,你就住在其中一个,你的朋友要来找你,如果房间没有编号,那么就要一间一间去找,这样等你的朋友找到你,大概也天黑了,但是如果每个房间都有自己的编号,如:一楼:101,102.......        二楼:201,202.....以此类推,这样你的朋友就可以快速找到你。

 其实计算机中的内存也是通过这样管理的,我们知道计算机CPU在处理数据的时候,需要的数据是在内存中读取的,用完了在放回内存中。

计算机也是把内存划分为一个个的内存单元,每个内存单元的大小是1字节。

补充:一个比特位可以储存一个2进制的位1或0。

bit- 比特位                    1byte = 8bit
byte- 字节                    1KB = 1024byte
KB                            1MB = 1024KB
MB                            1GB = 1024MB
GB                            1TB = 1024GB
TB                            1PB = 1024TB
PB

把这些每一个内存单元想成一个房间,一个房间可以放8个比特位。

把每个内存单元的编号想成一个内存的地址。

总结就是:内存单元的编号==地址==指针

1.2 编址

计算机中的编址,不是把每个字节的地址记录下来,而是通过硬件设计来完成的。就比如许多乐器的规则,都是设计者设计好的,所有人都遵循这个规则。其实本质上就是一直约定出来的共识。

2. 指针的变量和地址

2.1 取地址(&)

知道了内存和地址,其实在C语言中创建变量就是向内存申请一块空间。

 向这样的地址a我们应该如何得呢?

这时就要用到我们的一个操作符(&)——取地址操作符

#include <stdio.h>
//%p--打印地址
int main()
{int a = 10;printf("%p\n", &a);return 0;
}

 我们知道整型变量是占4个字节,这里我们只要知道第一个地址,就可以访问到4个字节的数据了

2.2 指针变量

当我们通过&得到的地址也是一个数(0x0023DF32),这个数值有时候也要储存起来,方便我们后面的使用。但是我们应该存放到哪呢?答案就是:指针变量。

#include <stdio.h>
int main()
{int a = 10;int* p = &a;//把a的地址储存在p这个指针变量中。return 0;
}

注意:指针变量也是变量,这种变量是用来存地址的,只要存放在指针中的值都会理解为地址。

 指针的类型:

int a=10;
int* p=&a;

这里的* 是在说明平时指针变量,而int 是在说明p指向的是整型类型的对象。

2.3 解引用

我们现在知道怎么把地址保证起来了,但是要怎么使用呢?在现实生活中,我们每个房间都会有一把打开它的钥匙,用了钥匙我们就可以打开房间,找到里面的东西。C语言其实也是一样的,我们拿到了地址,就可以通过地址找到地址指向的对象。这里就要用到解引用操作符 *()。

#include <stdio.h>
int main()
{int a = 10;int* p = &a;//把a的地址储存在p这个指针变量中。*p = 0;//解引用p,找到a并且将它的值改为0printf("%d", *p);return 0;
}

2.4 指针变量大小

#include <stdio.h>
//指针变量的⼤⼩取决于地址的⼤⼩
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{printf("%zd\n", sizeof(char*));printf("%zd\n", sizeof(short*));printf("%zd\n", sizeof(int*));printf("%zd\n", sizeof(double*));return 0;
}

3. 指针变量类型存在的意义

 其实指针类型是有特殊意义的,不同的类型有不同的意义。

3.1 不同类型指针的解引用

我们先看两个程序:

#include <stdio.h>
int main()
{int n = 0x11223344;int* pi = &n;*pi = 0;return 0;
}
#include <stdio.h>
int main()
{int n = 0x11223344;char* pc = (char*)&n;*pc = 0;return 0;
}

通过调试我们发现第一个程序会把n的4个字节全部改为0,而第二个程序只会把第一个字节改为0

总结:指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节)

3.2 指针对整数的运算(+,-)

我们可以看到,char*类型的指针变量+1跳过1个字节,int* 类型的指针变量+1,跳过4次字节。

总结:指针的类型决定了指针向前或者向后走一步的距离。

3.3 void* 指针

在指针类型中有void*类型的,我们可以理解为没有具体类型的指针(泛指针),这种指针可以接收任意类型的地址。但是,void* 不能用来直接进行指针的加减整数和解引用运算。

 注:⼀般 void* 类型的指针是使⽤在函数参数的部分,⽤来接收不同类型数据的地址,这样的设计可以 实现泛型编程的效果。使得⼀个函数来处理多种类型的数据。

4. const 修饰

4.1 const 变量

只要是变量,就是可以修改的。如果我们要想要这个变量成为不可变的,那么就要用到 const 来修饰。

 4.2 const(指针变量)

举例:

#include <stdio.h>
//代码1
void test1()
{int n = 10;int m = 20;int* p = &n;*p = 20;p = &m; 
}
void test2()
{//代码2int n = 10;int m = 20;const int* p = &n;*p = 20;p = &m; 
}
void test3()
{int n = 10;int m = 20;int* const p = &n;*p = 20;p = &m; 
}
void test4()
{int n = 10;int m = 20;int const* const p = &n;*p = 20; p = &m; 
}
int main()
{//测试⽆const修饰的情况test1();//测试const放在*的左边情况test2();//测试const放在*的右边情况test3();//测试*的左右两边都有consttest4();return 0;
}

结论:const修饰指针变量的时候

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

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

5. 指针的运算

指针的基本运算有三种,分别是:

 指针+- 整数——根据指针变量的类型,向前或向后移动

 指针-指针

 指针的关系运算

 6. 野指针

概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)——没有约束的指针

产生野指针的原因:
1. 指针没有初始化

2. 指针越界访问 ——只有10个元素,但是访问到第11个

3. 指针指向的空间被释放——指针指向函数

避免野指针的方法:
1. 指针初始化:指针一定要指向一个地址,没有就给指针赋值NULL(0)

2.小心指针越界:⼀个程序向内存申请了哪些空间,通过指针也就只能访问哪些空间。

3. 指针变量不再使用时一定要及时置为NULL,指针使用之前检查有效性。

4. 避免返回局部变量的地址

7. assert断言

assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报错终⽌运⾏。这个宏常常被称为“断⾔”。

assert (p!=NULL)
//验证p是否等于NULL
//当p不等于NULL时,程序继续运行,否则停止,并且给出报错信息

assert 的实现:assert() 宏接受⼀个表达式作为参数。如果该表达式为真(返回值⾮零),assert() 不会产⽣ 任何作⽤,程序继续运⾏。如果该表达式为假(返回值为零), assert() 就会报错,在标准错误流 stderr 中写⼊⼀条错误信息,显示没有通过的表达式,以及包含这个表达式的⽂件名和⾏号。

使用的优点:可以自动标识文件和出问题的行号,还有⼀种⽆需更改代码就能开启或关闭 assert() 的机制。

补充:如果已经确认程序没有问题,不需要再做断⾔,就在 #include 语句的前⾯,定义⼀个宏 NDEBUG

8.指针的使用和传址调用

举例1:strlen 的模拟实现

#include<assert.h>
int my_strlen(const char* str)
{int count = 0;assert(str);//断言判的str是否为真(非0)while (*str){count++;str++;}return count;
}
int main()
{int len = my_strlen("abcdef");printf("%d\n", len);return 0;
}

传址调用
例如:写⼀个函数,交换两个整型变量的值

我们一般的想法(传值调用):

 注意:实参传递给形参的时候,形参会单独创建⼀份临时空间来接收实参,对形参的修改不影响实参。

如果把要交换值的地址传给函数呢?

我们可以看到交换成功了。这种把变量的地址传递给了函数的方式叫:传址调用

补充:传址调⽤,可以让函数和主调函数之间建⽴真正的联系,在函数内部可以修改主调函数中的变量;所以未来函数中只是需要主调函数中的变量值来实现计算,就可以采⽤传值调⽤。如果函数内部要修改主调函数中的变量的值,就需要传址调⽤。

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

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

相关文章

(10)ATF MMU转换表

MMU简介 MMU&#xff08;内存管理单元&#xff09;负责将软件使用的虚拟地址转换为内存系统中使用的物理地址。MMU包括两个模块&#xff1a;TLB&#xff08;Translation Lookaside Buffer&#xff09;和TWU&#xff08;Table Walk Unit&#xff09;。TLB缓存最近使用的转换&am…

Spring Beans;Spring Bean的生命周期;spring Bean的作用域,spring处理线程并发问题

文章目录 Spring Beans请解释Spring Bean的生命周期解释Spring支持的几种bean的作用域Spring容器中的bean可以分为5个范围&#xff1a; Spring如何处理线程并发问题&#xff1f; 在现在的项目开发中经常使用到spring bean&#xff0c;那么来谈谈spring bean的生命周期&#xff…

APP软件线上排查方法

在线上环境中排查APP软件的问题是一项关键任务&#xff0c;需要使用一系列方法和工具来识别、定位和解决问题。以下是一些建议的排查方法&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.监控和日志…

linux如何查看文件的hash数值

在Linux系统中&#xff0c;你可以使用各种工具来查看文件的哈希值。下面是一些常见的方法&#xff1a; md5sum命令&#xff1a; md5sum 文件名例如&#xff1a; md5sum example.txtsha1sum命令&#xff1a; sha1sum 文件名例如&#xff1a; sha1sum example.txtsha256sum命令&a…

代码规范有用吗?听听100W年薪谷歌大佬怎么说!

谷歌内部的 python 代码规范 熟悉 python 一般都会努力遵循 pep8 规范&#xff0c;也会有一些公司制定内部的代码规范。大公司制定规范的目的不是说你一定要怎样去使用编程语言&#xff0c;而是让大家遵守同一套规则&#xff0c;节省其他人阅读代码的成本&#xff0c;方便协作…

红酒按照糖含量怎么分类?

我们常听人们形容葡萄酒为干型或甜型&#xff0c;这指的是葡萄酒的含糖量。不含糖就是干型&#xff0c;含糖少就是半干型&#xff0c;含糖多就是甜型&#xff0c;这是葡萄酒分类的一种——按糖量分。云仓酒庄的品牌雷盛红酒分享一般分为干型、半干型、半甜型、甜型四种。 云仓…

Jetson orin(Ubuntu20.04)不接显示器无法输出VNC图像解决办法以及vnc安装记录

sudo apt install vino 好像Jetpack 5.0中已经自带了。。 配置VNC server: gsettings set org.gnome.Vino prompt-enabled false gsettings set org.gnome.Vino require-encryption false 编辑org.gnome,增加一个“enabled key”的参数&#xff1a; cd /usr/share/glib-2…

氮化镓的晶体学湿式化学蚀刻法

引言 目前&#xff0c;大多数III族氮化物的加工都是通过干法等离子体蚀刻完成的。干法蚀刻有几个缺点&#xff0c;包括产生离子诱导损伤和难以获得激光器所需的光滑蚀刻侧壁。干法蚀刻产生的侧壁典型均方根(rms)粗糙度约为50纳米&#xff0c;虽然已经发现KOH基溶液可以蚀刻AlN…

服务台需要跟踪的3个重要指标MTBF+MTTF+MTTR

衡量标准是IT服务管理的核心&#xff0c;可提供有关运营的见解&#xff0c;并帮助确定需要持续改进的领域。通常的服务台指标有助于展示内部运营效率。例如&#xff0c;衡量在规定时间内解决问题的工单数量的 SLA 是展示服务台效率的关键因素。另一方面&#xff0c;故障指标可帮…

ate测试原理及ate测试系统(软件)知识科普 -纳米软件

ATE(Automatic Test Equipment)测试也叫自动化测试&#xff0c;通过计算机控制测试仪器对被测对象进行测试。以计算机编程代替人工测试&#xff0c;基于测试程序控制仪器并对待测品进行输入和输出信号检测分析&#xff0c;从而判断待测品的性能是否符合要求。 ATE测试需要根据测…

linux进程调度(一)-进程概述

一、什么是进程 进程是指计算机已运行的程序。程序本身只是指令、数据及其组织形式的描述。进程就是一个程序的执行实例&#xff0c;也就是正在执行的程序。在linux操作系统的中&#xff0c;进程就是一个担当分配系统资源CPU时间、内存的实体。进程控制的主要功能是对系统中的所…

2023年微软开源八个人工智能项目

自2001年软件巨头微软前首席执行官史蒂夫鲍尔默对开源&#xff08;尤其是Linux&#xff09;发表尖刻言论以来&#xff0c;微软正在开源方面取得了长足的进步。继ChatGPT于去年年底发布了后&#xff0c;微软的整个2023年&#xff0c;大多数技术都是面向开发人员和研究人员公开发…

HarmonyOS 设备管理开发:USB 服务开发指导

基本概念 USB 服务是应用访问底层的一种设备抽象概念。开发者根据提供的 USB API&#xff0c;可以获取设备列表、控制设备访问权限、以及与连接的设备进行数据传输、控制命令传输等。 运作机制 USB 服务系统包含 USB API、USB Service、USB HAL。 图 1 USB 服务运作机制 ●…

【SpringBoot3+Vue3】五【完】【实战篇】-前端(配合后端)

目录 一、环境准备 1、创建Vue工程 2、安装依赖 2.1 安装项目所需要的vue依赖 2.2 安装element-plus依赖 2.2.1 安装 2.2.2 项目导入element-plus 2.3 安装axios依赖 2.4 安装sass依赖 3、目录调整 3.1 删除部分默认目录下文件 3.1.1 src/components下自动生成的…

渲染农场渲染一分钟动画需要多少钱?需要渲染多少时间?

现在很公司都开始使用渲染农场渲染动画&#xff0c;但是还是有很多人不知道渲染农场渲染动画需要多少钱&#xff0c;需要渲染多少时间。在这篇文章中我们将为你一一解答&#xff0c;为你提供一个清晰的参考。 渲染农场的收费通常是按照渲染的使用时间收费&#xff0c;渲染十分…

华大基因助力乌兹别克斯坦精准医学发展,共筑健康丝绸之路

今年上半年&#xff0c;中国与中亚五国元首齐聚陕西西安&#xff0c;举办中国&#xff0d;中亚峰会。过去的20年里&#xff0c;中国已经成为中亚国家的主要投资来源国&#xff0c;总投资额接近400亿美元。乌兹别克斯坦是中国&#xff0d;中亚合作机制的重要参与者&#xff0c;乌…

CAD随机多面体_圆柱试件3D插件

插件介绍 CAD随机多面体_圆柱试件3D插件可用于在AutoCAD软件内生成随机三维多面体及外侧圆柱体试件。插件可确保多面体之间不发生干涉&#xff0c;且多面体与外侧圆柱体试件之间保持适配关系&#xff0c;确保生成的模型导入有限元软件后几何合理有效。本插件主要可应用于三维混…

讲概念谈愿景AI Agent名不副实?看实在智能RPA Agent智能体如何落地!

OpenAI在首届开发者大会上推出了GPTs和Assitant API&#xff0c;不仅改写了AI Agent的构建范式&#xff0c;也把AI智能体的应用推向一个新高潮。GPTs和GPT商店&#xff0c;使得用户无需编码通过自然语言就能创建并拥有多个专属私人助理&#xff0c;且可以如在苹果应用商店一样在…

Y-MODEM协议定制上位机

最近在使用N32G031和STM32F10X系列单片机进行IAP&#xff0c;使用的是Ymodem协议。单片机上的软件已经完成了&#xff0c;一般是使用secureCRT这样的工具作为上位机来进行测试&#xff0c;后来想做一个定制化的简单的上位机。在网上找了下资料&#xff0c;以下这篇文章写的使用…

浅谈安科瑞无线测温设备在挪威某项目的应用

摘要&#xff1a;安科瑞无线温度设备装置通过无线温度收发器和各无线温度传感器直接进行温度值的传输&#xff0c;并采用液晶显示各无线温度传感器所测温度。 Absrtact:Acre wireless temperature device directly transmits the temperature value through the wireless temp…