【C语言】指针篇-初识指针(1/5)
🌈个人主页:是店小二呀
🌈C语言笔记专栏:C语言笔记
🌈C++笔记专栏: C++笔记
🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅
文章目录
- **内存和地址(知识铺垫(了解即可))**
- 如何理解编址
- **指针变量**
- **指针的初始化和赋值运算**
- **指针变量的大小**
- **指针变量类型的意义**
- **指针+-整数**
- const修饰指针
- const修饰变量
- const修饰指针变量
- **指针运算**
- **野指针**
- **assert断言(assert.h头文件定义了宏assert())**
- **传值调用和传址调用**
内存和地址(知识铺垫(了解即可))
内存(Memory)是计算机的重要部件,也称内存储器和[主存储器]它用于暂时存放CPU中的运算数据,以及与硬盘等[外部存储器]交换的数据。
当CPU(中央处理器)在处理数据的时,需要的数据是在内存中读取的,处理后的数据也会放回内存中。
问题:那么内存空间如何高效的管理的呢?
- 是将内存划分为一个个的内存单元,每个内存单元的大小取一个字节(一个字节等于八个比特位,比特bit是二级制位(Binary digit)的简称,一个二进制包含的信息量成为一比特bit。)
- 每个内存单元都有一个编号(相当于宿舍房间的门牌号),有这个内存单元的编号,CPU就可以通过这个编号快速找到一个内存空间
- 在计算机中我们把内存单元的编号也称为地址。C语言给地址起了个新名字位指针,这里解释了计算机中内存是按照字节编址的,也是每个字节都有唯一的地址,而对于比特是没有地址
- 可以理解为:内存单元的编号==地址 ==指针;
如何理解编址
CPU访问内存中的某个字节空间,必须知道这个字节空间在内存的什么位置,因为内存中有很多字节,所以需要给内存进行编制,计算机中的编址不是把每个字节的地址都记录下,而是通过硬件设计完成。
钢琴、吉他上面没有写上“都瑞咪发嗦啦”这样 的信息,但演奏者照样能够准确找到每⼀个琴弦的每⼀个位置,这是为何?因为制造商已经在乐器硬件层面上设计好了,并且所有的演奏者都知道。本质是⼀种约定出来的共识!
首先,计算机内是有很多硬件单元的,而硬件单元是要相互协同工作,既然是协同工作,至少之间要能够进行数据传递,但是硬件和硬件之间是互相独立的,那么如何通信呢?那么需要通过"线"连起来,那么CPU和内存之间也是有大量的数据交互,所以这两者必须也用线连起来。
这里只关注一组线:地址总线
可以简单理解为32位机器有32根地址总线,那么每根线只有两态,表示0,1【电脉冲有无】,一根线能代表两种含义,两根线就能表示四种含义,依次类推。32根地址线,就能表示2^32种含义,每一种含义都代表一个地址。
地址信息被下达给内存,在内存上,就可以找到地址对应的数据,将数据在通过数据总线传入CPU内寄存器中
##正文
指针变量
了解内存和地址的关系,可知创建变量需要向内存申请一定大小的空间
指针变量时用于存放其他变量的地址(其他变量在内存中存储的位置),简称指针。指针本身是一种变量,需要占用一定大小的空间的,用来存放指针值(指针变量本身的地址)。
指针定义说明的一般形式:
类型说明符(void) *指针变量名(name);
*表示pa是一个指针变量
类型说明符表示指针变量指向什么类型的对象
比如:
int p=1;char q='a';
int *pa=&p;说明指针变量pa是指向int类型变量的指针
char *qa=&q;说明指针变量qa是指向char类型变量的指针
注意:
- 指针变量值表达的是某个数据对象的地址,只允许取正的整数值的。
- 但是他不等同于整形类型变量,如果指针变量取0值,即为NULL(空),则表示指针指向对象不存在,为空指针
指针的初始化和赋值运算
```类型说明符 指针变量名=初始化地址值``
注意:
- 初始化中也是将初始地址赋值给指针变量
- 在赋值语句中,变量的地址也只能赋值给指针变量,这种赋值运算操作限制在同类之间
## 指针运算符(& 、*)
取地址操作符 &:返回存放其他变量的内存地址(只限于一个具体的变量或数值元素,不可用于表达式)
int p=1;
int *pa=&p;//这里pa存放p的地址
*解引用操作符 :返回地址(指针标量指向的地址)中的变量值
int p=1;
int *pa=&p;//这里pa存放p的地址
int ret=*pa//ret==1
这里样对于变量的修改,多了一种途径,写代码就会更加灵活
指针变量的大小
通过前面“内存和地址”,32位机器有32根地址总线,每根地址线出来的电信号转换成数字信号后(1或0),将32根地址线产生的二级制序列当做一个地址,那么一个地址需要32个bit位,也是4个字节存储。那么在64位机器,有64根地址总线,一个的地址就是64个二级制位组成的二级制序列,那么一个需要地址需要64个bit位,也是8个字节存储。
小总结:
指针变量是用来存放地址的,那么在不同机器下,地址的大小也会影响指针变量的大小
- 32位平台下地址是32个bit位,指针变量大小是4个字节
- 64位平台下地址是64位bit位,指针变量大小是8个字节
- 指针变量的大小和类型是无关的,只要指针类型的变量,在相同的平台下,大小都是相同的
指针变量类型的意义
既然指针变量的大小与指向的类型无关,那么为什么要区分各种指针类型呢?
那当然是因为指针类型在其他方面有特殊的意义
#include <stdio.h>int main()
{int n=0x11223344;int *p1=&n;*p=0;int m=0x11223344;char *p2=(char *)&m;//原本&m 应该由int *类型存储*pc=0;return 0;
}
这里涉及到了大小端的知识,理解指针类型对解引用的影响
如图可得的,n的四个字节全部改为0,而m只是第一个字节改为0
结论:指针的类型决定,对指针解引用能修改几个字节的权利
拿上面的例子:
-
n是int 类型(占四个字节,其中两个数字算一个字节),int *指针类型指向n的地址,*当解引用的时候,int 指针只能访问四个字节
-
m是char 类型(占一个字节,其中两个数字算一个字节),char *指针类型指向m的地址,*当解引用的时候,char 指针只能访问一个字节(修改44)
指针±整数
代码:
#include <stdio.h>
int main()
{
int n = 10;
char *pc = (char*)&n;
int *pi = &n;
printf("%p\n", &n);printf("%p\n", pc);
printf("%p\n", pc+1);printf("%p\n", pi);
printf("%p\n", pi+1);
return 0;
}
结论:指针类型决定了指针向前或者向后走一步有多大(距离)。char *类型的指针变量+1跳过1个字节,int *类型的指针变量+1跳过了4个
const修饰指针
const修饰变量
如果不希望这个变量被修改,可以使用const进行限制。
int main()
{const int m=0;m=1;//ok?
}
上边的代码:使用const修饰(语法上加了限制),只要对n变量进行修改,就不符合语法规则,就会报错,对于const修饰后的变量是不能进行直接修改的.
通过上面刚学的一种修改变量的方法,通过n的地址取修改n值(打破语法规则)
int main()
{const int m=0;int *p=&m;*p=20;return 0;
}
这样子n变量还能被修改,const使用的就没有多大意义,这样子不是自己打自己脸吗?那么有什么办法p拿到了n的地址也不能修改n值(对指针下手)。
const修饰指针变量
int main()
{int m=0;int n=1;第一种:const int *pa=&m;pa=&n;*pa=10;//右边为不可修改值第二种: int * const pa=&m;pa=&n;//左边为不可修改值*pa=10;
}
总结:当const修饰指针变量的时候
- const放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变,但是指针变量本身的内容可变
- const放在*的右边,修饰的是指针变量本身,保证指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变
指针运算
指针的基本运算有三种
1.指针±整数(在连续存放的数据,只要知道第一个元素的地址,就可以知道后面所有的地址),这里整数也称为偏移量
数组int main()
{int nums[]={1,2,3,4,5};int *p=nums;//首元素的地址printf("%d",*(p+2));//那么p的偏移量为+2,打印结果是3return 0;
}
2.指针-指针
int main()
{char *p="abcd";//不要忘记还有'\0'char *s=p;while(*p!='\0'){p++;}int ret=p-s;//4printf("%d",ret); return 0;
}
结论:指针减指针表示指向两个指针之间的元素个数,求首元素到某个元素之间相错个数(在连续存储的情况下)
3.指针的关系运算
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;
野指针
野指针;指针指向位置是不可知的(具有不确定因素)
下列有几种野指针的成因:
1.指针未初始化int *p;
2.指针越界访问(数组越界访问)
int nums[10]={0};
int *p=nums;
for(int i=0;i<11;i<++)
{*(p++)=i;
}
3.指针指向的空间释放
int* test()
{int m=0;return &m
}
int mian()
{int *p=test();printf("%d\n",*p);return 0;
}
m是一个被销毁的局部变量,这里指针指向m所在的位置空间是不明确的,原本属于m的空间,可能被给了其他变量占用,这样子就导致程序可能不能达到预期效果
规避野指针
1.确定指针指向一片有效的空间,如果指针目前没有指向,可以为指针赋值为NULL,NULL是一个定义的标识符常量,值为0,0也是地址,这个地址是无法使用的
2.当指针变量不再使用,设置为NULL,指针使用之前检查有效性(判断语句或者断言)
3.规定:只要指针为NULL就不去访问,但是给野指针赋值为NULL,将野指针暂时管理起来,还是存在危险的。
assert断言(assert.h头文件定义了宏assert())
作用:当符合程序符合指定条件,没有啥影响,如何不符合条件,就会报错终止运行。而这个宏常称为断言。
具体使用细节:
#inlclude <assert.h>
int p=0
assert(p!=0);
- assert()宏接受一个表达式作为参数。如果表达式为真(返回值为非零),没有啥影响,程序继续执行。
- 如果表达式为假(返回值为零),assert()就会报错,在标准报错流中stderr中写入一条错误信息(显示没有通过的表达式、表达式文件名和行号)
好处:
- 自动标识文件和出问题的行号
- 存在一种无需更改代码就能开启或关闭assert()的机制,就是在
#include <assert.h>
语句的前面,定义一个宏NDEBUG
#define NDEBUG
#include <stdio.h>
对于宏NEDBUG
使用时,编译器就会禁用文件中assert()语句
。如果程序出现问题,可以注释掉,就可以重新启动assert()语句
不足:assert()
的引入了额外的检查,增加了程序的运行时间
- 在
debug
和release
版本下,一般debug
调试中使用,在release(发布版本)
选择禁用assert
,提高程序效率。 - 在VS这样的集成开发环境中,
release
版本中,直接优化掉了。
总结:debug版本有利于程序员排查问题,release版本不行用户使用程序的效率
传值调用和传址调用
在函数章节,提到形参是实参的一份临时拷贝,形参的改变不会影响到实参
#include <stdio.h>
void Swap(int x,int y)
{int tmp=x;x=y;y=tmp;
}
int main()
{int a=10;int b=20;Swap(a,b);
}
这里x和y的值等于a和b的值,但是各属于独立的空间,那么x和y值交换,不会影响到实参a和b值的交换
对于这种将变量的数值传递给函数,调用方法:传值调用
对此可以使用指针
#include <stdio.h>
void Swap(int *x,int *y)
{int tmp=*x;*x=*y;*y=tmp;
}
int main()
{int a=10;int b=20;Swap(&a,&b);
}
这里在main函数中将a和b的地址传递给了Swap函数,Swap函数通过地址间接的操作main函数中的a和b
对于这种将变量的地址传递给函数,调用方法:传址调用
谢谢大家的观看,这里是个人笔记,希望对你学习C有帮助。
相关文章:
【C语言】指针篇-初识指针(1/5)
🌈个人主页:是店小二呀 🌈C语言笔记专栏:C语言笔记 🌈C笔记专栏: C笔记 🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅 文章目录 **内存和地址(知识铺垫(了解即可))**如何理解编址**指针变量*…...
【御控物联】物联网平台设备接入-JSON数据格式转化(场景案例四)
文章目录 一、背景二、解决方案三、在线转换工具四、技术资料 一、背景 物联网平台是一种实现设备接入、设备监控、设备管理、数据存储、消息多源转发和数据分析等能力的一体化平台。南向支持连接海量异构(协议多样)设备,实现设备数据云端存…...
stack和queue模拟实现
前言 上一期我们介绍了stack和queue的使用,本期我们来模拟实现一下他们! 本期内容介绍 容器适配器 deque介绍 为什么stack和queue的底层选择deque为默认容器? stack 模拟现实 queue 模拟实现 什么是容器适配器? 适配器是一种设…...
docker操作
1、容器生命周期管理命令 docker run docker run --name tomcat8 -d -p 28080:8080 tomcat:8.5.38 docker run -i --name hausf --network bridge --ip 172.17.0.10 ubuntu:20.04 /bin/bash docker run -d --name hausf --net host ubuntu:20.04 /bin/bash docker run…...
分布式锁介绍
引言 分布式锁是一种用于协调不同进程或线程对共享资源的访问控制的机制。在分布式系统中,由于多个节点可能同时访问或修改同一资源,因此需要一个中心化的协调机制来确保资源的访问是有序的,避免数据不一致的问题。 分布式锁的特性…...
Unity 获取RenderTexture像素颜色值
拿来吧你~ 🦪功能介绍🌭Demo 🦪功能介绍 💡不通过Texture2D 而是通过ComputerShader 提取到RenderTexture的像素值,效率有提升哦! 💡通过扩展方法调用,方便快捷:xxxRT.G…...
Tomcat以服务方式启动,无法访问网络共享目录问题
关于“Tomcat以服务方式启动,无法访问网络共享目录问题”解决方式如下: 1、通过doc命令【services.msc】打开本地服务找到,找到tomcat服务所在位置 2、右键打开Tomcat服务的属性 3、选择 登陆选项卡 4、选择“此账户”选项,并…...
SVN的介绍
首先SVN是什么: Apache下的一个开源的项目Subversion,通常缩写为 SVN,是一个版本控制系统。 版本控制系统是一个软件,它可以伴随我们软件开发人员一起工作,让我们编写代码的完整的历史保存下来。 目前它的各个版本的…...
ZYNQ-700呼吸灯
参考野火例程 实现呼吸灯即要调整led亮的占比时间,完成视觉上看起来由灭到亮或者由亮到灭的过程。 如果主频为50MHz,理论上一秒钟我们可以控制50_000_000次led的亮和灭,肉眼不可能分辨出来每一次亮灭,如果这50M我们设定为间隔一…...
UE5学习日记——制作多语言版本游戏,同时初步学习UI制作、多语言化、控制器配置、独立进程测试、打包配置和快速批量翻译等
所有的文本类,无论变量还是控件等都能实现本地化,以此实现不同语言版本。 在这里先将重点注意标注一下: 所有文本类的变量、控件等都可以多语言;本地化控制板中收集、编译时,别忘了编译这一步;支持批量复制…...
电脑重启后word文档空白或打不开,word无法自动修复,如何拯救
最近编辑word文档,写了好几个星期的内容随着电脑重启的一瞬间,灰飞烟灭,让我简直痛不欲生! 好在,天无绝人之路,以下两个方法拯救了地球 第一,普通的文档word自动修复不好使的时候,…...
MVC和MVVM这两种设计模式的区别
一、MVC和MVVM是什么? MVC是Model-View-Controller的简写,Model就是模型,对应后端数据,View就是视图对应用户界面,Controller就是控制器,对应页面的业务逻辑。 MVC的工作机制原理就是,用户操作…...
淘宝app端商品详情数据采集(商品价格,商品库存,商品销量,商品优惠券)
在淘宝App端采集商品详情数据,包括商品价格、库存、销量以及优惠券信息,可以通过多种方式实现。以下是几种常见的方法: 使用淘宝开放平台API: 淘宝开放平台提供了一系列API接口,这些接口允许开发者获取淘宝商品的详细…...
第42篇:随机存取存储器(RAM)模块<一>
Q:本期开始我们分期介绍随机存取存储器(RAM)模块及其设计实现方法。 A:随机存储器RAM,即工作时可以随时从一个指定地址读出数据,也可以随时将数据写入一个指定的存储单元。 DE2-115开发板上的Cyclone IV …...
在Java中实现记录1000万用户连续7天登录的功能,可以使用Redis的Bitmap来跟踪每个用户的登录状态
在Java中实现记录1000万用户连续7天登录的功能,可以使用Redis的Bitmap来跟踪每个用户的登录状态。以下是一个简化的Java示例,使用了Jedis库作为Redis的Java客户端。 首先,确保你已经在项目中添加了Jedis的依赖。如果你使用Maven,…...
深入探讨VIVE OpenXR:为Unity开发者的全面指南
随着虚拟现实(VR)和增强现实(AR)技术的迅速发展,开发者们对于能够简化和优化沉浸式应用开发的工具需求日益增长。HTC Vive 作为行业内的领先品牌,其最新推出的 VIVE OpenXR 插件为Unity开发者提供了一个强大…...
【Altium Designer 20 笔记】PCB线宽与过孔尺寸
电源线:40mil1A(一般翻倍给),地线比电源线粗一点即可;信号线:10-15mil 一、线宽 市电的火线和零线:80-100mil12V /24V 20mil~60mil 5V 20-30mil 3V 20-30mil GND 越宽越好20-30mil普通信号线 10mil-15mil…...
基于java的社区生活超市管理系统
开发语言:Java 框架:ssm 技术:JSP JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:eclipse/myeclip…...
51单片机入门_江协科技_27~28_OB记录的自学笔记_AT24C02数据存储秒表
27. AT24C02(I2C总线) 27.1. 存储器介绍 27.2. 存储器简化模型介绍,存储原理 27.3. AT24C02介绍 •AT24C02是一种可以实现掉电不丢失的存储器,可用于保存单片机运行时想要永久保存的数据信息 •存储介质:E2PROM •通讯接口:I2…...
LeetCode-热题100:169. 多数元素
题目描述 给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: nums [3,2,3] 输出…...
汽车维修类中译英的英语翻译
近年来,随着全球化的加速和汽车市场的不断扩大,汽车维修领域的交流与合作也日益频繁。汽车维修类中译英的英语翻译在汽车行业中扮演着至关重要的角色。那么,针对汽车维修类翻译,中译英的英语翻译有何技巧? 业内人士指出…...
java中的List,ArrayList和LinkedList集合
List集合: void add(int index, E element) Inserts the specified element at the specified position in this list (optional operation). 在此集合中的指定位置插入指定元素 E remove(int index) Removes the element at the specified position in this list (…...
RESTful API与Web应用程序构建:原理与实践
在现代Web开发中,RESTful API已经成为构建应用程序的核心组件之一。RESTful API不仅为前后端分离的开发模式提供了强有力的支持,还使得不同服务和应用之间的数据交互变得简单高效。本文将深入探讨RESTful API的原理,并展示如何使用它来构建We…...
输了,腾讯golang一面凉了
本月正值4月,是金三银四的找工作的最佳时机。同时竞争也是很大,因为每年这个时候快要毕业的大学生也进去了找工作的潮水中。 今天分享我的一位大佬朋友CC,勇闯腾讯golang的面试经历。 这次面试问题的方向主要集中在计算机基础个网络方面。 下面是主要问到的问题。 第一个…...
如何通过代码签名证书加强安全防护?
在当今数字化时代,安全防护是用户和企业保护其数据和应用程序免受恶意攻击的关键。代码签名证书是一种通过数字签名来验证软件代码来源和完整性的安全工具。通过对软件代码进行数字签名,代码签名证书可以加强安全防护,防止恶意软件和篡改攻击…...
Docker速成:新手变专家!
Docker介绍 容器历史 1、Chroot Jail 就是常见的chroot命令的用法。它在1979年的时候就出现了,被认为是最早的容器化技术之一。它可以把一个进程的文件系统隔离起来。 2、The FreeBSD Jail (监狱)实现了操作系统级别的虚拟化,他…...
numpy/arrayobject.h: No such file or directory
catkin编译时出现,numpy/arrayobject.h: No such file or directory 错误表明编译过程中找不到 NumPy 相关的头文件。这通常是因为环境中的 NumPy 没有被正确配置到包含路径中,或者 NumPy 没有被安装。以下是几个解决步骤来帮助你解决这个问题: 确认 NumPy 已安装 首先,确保…...
前端大文件分块上传、断点续传
文章目录 前端分块上传流程分块上传代码重点1. let start currentChunk * chunkSize;2. let end Math.min(file.size, start chunkSize);3. let chunk file.slice(start, end); 结合断点续传注意事项 大文件上传是一个复杂的过程,尤其是在前端,我们需…...
使用新版FLIR (FLIR_ADAS_v2) 数据集创建yolo格式数据集(目标检测)
FLIR在2022.1.19发布了新版的FLIR_ADAS_v2,有着更多的类别和数量更丰富的图像。数据集同步注释热图像和无注释RGB图像供参考。本文章主要介绍如何使用FLIR_ADAS_v2中的rgb图像和thermal图像来制作yolo格式数据集。 1.官方数据集下载:FLIR_ADAS_v2数据集…...
PHP发票查验接口未返回正确信息的原因、发票ocr识别接口
发票查验接口未返回正确信息的原因一般有以下几种,第一种可能是接口没有调通,第二种是本身这张发票就是一张错票、假票,第三种可能是税局系统或者网络问题等等。那么,遇到这种情况应该如何解决呢?翔云发票查验接口&…...
用php做网站/网站权重划分
点击蓝色字免费订阅,每天收到这样的好资讯本文将完全卷积神经网络应用于Phenoliner表型平台,并检测捕获的图像中的单个葡萄浆果,植物表型资讯介绍如下:在葡萄育种栽培领域,产量估算和预测具有重要意义,每株…...
怎么做网站弹幕/seo站长工具是什么
源面板,又称源监视器。其主要作用是:预览源剪辑、选取片段、插入或覆盖剪辑到时间轴面板。◆ ◆ ◆在源面板查看媒体内容双击项目面板里的源剪辑文件图标,即可将源剪辑载入源面板,也可直接拖入至源面板。提示:如果没…...
怎么让人理解网站建设/广州疫情最新动态
使用session_set_save_handler()函数,将Session的内容写入数据库/*[email protected] Fahy*数据库为mysql,*数据库名为session,表名为session,*表中字段包括PHPSESSID,update_time,client_ip,data*/class Session{private static …...
济南中京网站建设公司/设计网站官网
文档测试如果你经常阅读Python的官方文档,可以看到很多文档都有示例代码。比如re模块就带了很多示例代码:>>>import re>>>m re.search((?<abc)def,abcdef)>>>m.group(0)def这些文档和其他说明可以写在注释中,然后&#…...
网站规划建设方案农业绿化风格/互联网推广的方式
当你通过后台拿到数据,而这个数据是带标签的字段,跟vue框架中的v-html指令功能一样 场景:例如后台富文本编辑器编写的一些文章然后生成html,然后接口返回给c端显示 <!-- publishData的值是一段html,比如࿱…...
如何建设公司的网站/网站排名
请确保具备以下条件: Internet 连接。 计算机C盘大于6 GB 的可用空间用于下载。 8GB的U盘。建议使用空白U盘,因为其中的任何内容都将被删除。重要信息 建议在运行 Windows7 或Windows8.1 的电脑上使用介质创建工具。如果你在运行Windows10 的电脑上运行此…...