c语言进阶部分详解(指针初阶)
大家好!,前段时间一直在准备数学建模竞赛,现在也是忙完了。抓紧继续给大家带来c语言的内容。今天给大家带来指针初阶部分的讲解
当我们谈论C语言中的指针时,实际上是在讨论一种非常重要的概念,因为指针是C语言的核心之一。它们允许我们直接访问内存中的数据,这在编写高效和灵活的程序时非常有用。让我们来深入了解一下指针的概念和用法
目录
一.指针是什么
1.指针的初步理解
2.指针的大小
3.总结
二.指针和指针类型
三.指针类型的意义
1.指针+-整数
2.解引用
四.野指针
1.野指针成因
①指针未初始化
②指针越界访问
编辑
③指针指向的空间释放
五.指针运算
1.指针+-整数
2.指针-指针
3.指针的关系运算
4.注意
六.指针和数组
七.二级指针
八.指针数组
一.指针是什么
1.指针的初步理解
指针理解的2个要点:1. 指针是内存中一个最小单元的编号,也就是地址2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量总结:指针就是地址,口语中说的指针通常指的是指针变量
指针变量:我们可以通过 & (取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个变量就是指针变量
#include<stdio.h>
int main()
{int a = 7;//创建变量时,在内存里开辟的一篇空间int* pa = &a;//这里我们对变量a,取出它的地址,可以使用&操作符//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量//中,p就是一个之指针变量return 0;
}
总结:指针变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)
2.指针的大小
在C语言中,指针的大小是根据计算机体系结构和操作系统的不同而变化的。通常情况下,指针的大小与计算机的位数相关。在32位系统中,指针的大小通常是4字节(32位),而在64位系统中,指针的大小通常是8字节(64位)
3.总结
- 指针是用来存放地址的,地址是唯一标示一块地址空间的。
- 指针的大小在32位平台是4个字节,在64位平台是8个字节
二.指针和指针类型
变量有不同的类型,整形,浮点型等。那指针有没有类型呢?
指针确实有:
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
这里可以看到,指针的定义方式是: type + * 。其实:char* 类型的指针是为了存放 char 类型变量的地址。short* 类型的指针是为了存放 short 类型变量的地址。int* 类型的指针是为了存放 int 类型变量的地址
接下来探求指针类型的意义
三.指针类型的意义
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)
比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节
1.指针+-整数
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;
}
2.解引用
可以看到pc与pi的数值均是相等的,当运行完*pc=0后,只是改变了第一个字节的数值。
当运行完*p=0后,只是改变四个字节的数值
四.野指针
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
1.野指针成因
①指针未初始化
int main()
{int* pa;*pa = 10;return 0;
}
连编译器都会阻止我们使用未初始化的指针
②指针越界访问
int main()
{int arr[10] = { 0 };int* p = arr;for (int i = 0; i <= 11; i++){*(p++) = i;}return 0;
}
当指针指向的范围超出数组arr的范围时,p就是野指针: 自然也会报错
③指针指向的空间释放
int* createInt() {int num = 5;int* ptr = #return ptr;
}int main() {int* ptr = createInt();printf("%d\n", *ptr); // 输出5,但是这是不安全的操作// 在这之后,ptr成为了野指针,因为它指向的内存空间已经被释放printf("%d\n", *ptr); // 未定义的行为,可能输出垃圾值或导致程序崩溃return 0;
}
在上面的示例中,函数
createInt()
创建了一个整型变量num
,并将其地址赋给指针ptr
,然后返回了该指针。在main()
函数中,我们打印了指针ptr
所指向的值,输出结果为5。但是在createInt()
函数结束后,变量num
的生命周期结束,其所占用的内存空间被释放。此时,指针ptr
仍然保留着之前的内存地址,成为了野指针。在后续的打印操作中,我们试图访问野指针ptr
所指向的值,这是不安全的操作,可能导致程序出现未定义的行为
五.指针运算
1.指针+-整数
- 指针加减整数是指对指针进行加减运算,其中整数表示要加减的偏移量。这种操作通常用于在指针上移动一定的距离,以便访问指针指向的内存位置
- 指针的加减运算是基于指针所指向的数据类型的大小进行的。例如,如果一个指针指向一个
int
类型的变量,那么对该指针进行加1的操作,将使指针指向下一个int
类型的变量。同样地,对指针进行减1的操作,将使指针指向前一个int
类型的变量
#include<stdio.h>
int main()
{int arr[] = { 1,2,3,4,5 };int* pa = arr;for (int i = 0; i < 5; i++){printf("%d ", *(pa++));}return 0;
}
2.指针-指针
指针-指针操作是指对两个指针进行减法运算,得到它们之间的偏移量。这种操作通常用于计算两个指针之间的距离或元素的个数
接下来我们可以利用这一点来模拟实现strlen()函数
int my_strlen(char* pa)
{char* start = pa;while (*pa){pa++;}return pa - start;
}int main()
{char arr[] = "hello";printf("%d", my_strlen(arr));return 0;
}
3.指针的关系运算
==
:判断两个指针是否相等。如果两个指针指向同一个内存地址,则它们相等,返回1
;否则返回0
。!=
:判断两个指针是否不相等。如果两个指针指向不同的内存地址,则它们不相等,返回1
;否则返回0
。>
:判断一个指针是否大于另一个指针。指针的大小是根据指针所指向的内存地址来比较的。如果第一个指针指向的地址在第二个指针指向的地址之后,则第一个指针大于第二个指针,返回1
;否则返回0
。<
:判断一个指针是否小于另一个指针。指针的大小是根据指针所指向的内存地址来比较的。如果第一个指针指向的地址在第二个指针指向的地址之前,则第一个指针小于第二个指针,返回1
;否则返回0
。>=
:判断一个指针是否大于等于另一个指针。如果第一个指针大于第二个指针或两个指针相等,则返回1
;否则返回0
。<=
:判断一个指针是否小于等于另一个指针。如果第一个指针小于第二个指针或两个指针相等,则返回1
;否则返回0
4.注意
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较
六.指针和数组
1.指针是一个变量,用于存储内存地址。指针变量可以指向任何类型的数据,包括数组。通过指针,我们可以间接地访问和操作内存中的数据。
2.数组就是数组,可以存放一组数,数组的大小是取决于元素的类型和个数。
3.数组的数组名是数组首元素的地址,地址是可以放在指针变量中的。通过指针可以访问一个数组的元素
- 数组名和指针:在C语言中,数组名可以被看作是一个指向数组首元素的指针。例如,对于数组
int arr[5]
,arr
可以被视为指向arr[0]
的指针。因此,可以通过指针来访问数组中的元素,例如*arr
表示数组的第一个元素,*(arr + 1)
表示数组的第二个元素。 - 此外,指针算术运算也可以应用于数组名。例如,
arr + 1
表示数组的第二个元素的地址,arr + 2
表示数组的第三个元素的地址。这是因为数组的元素在内存中是连续存储的
int main()
{int arr[] = { 1,2 };int* pa = arr;printf("%p\n", arr);printf("%p\n", &arr[0]);return 0;
}
可见数组名通常是表示数组首元素的地址,但是有两个例外:
1.sizeof(数组名),数组名单独放在sizeof内部,数组名表示整个数组,计算的是数组的大小,单位是字节。
2.&数组名,数组名表示整个数组,取出的是数组的地址,数组的地址和数组首元素的地址是一样的,但是类型和意义是不一样的
七.二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
这就是 二级指针
int main()
{int a = 10;int* pa = &a;//一级指针int** ppa = &pa;//二级指针printf("%d\n", a);**ppa = 0;//通过两次解引用来改变值printf("%d\n", a);return 0;
}
八.指针数组
指针数组是是数组,是存放指针的数组
可以使用指针数组,模拟一个二维数组
int main()
{int arr1[] = { 1,2,4,6 };int arr2[] = { 7,2,4,4 };int arr3[] = { 1,2,9,6 };int* p[] = { arr1,arr2,arr3 };for (int i = 0; i < 3; i++){for (int j = 0; j < 4; j++){printf("%d ", p[i][j]);}printf("\n");}return 0;
}
指针是C语言中一个强大而复杂的概念。通过使用指针,我们可以直接访问和修改内存中的数据,实现灵活和高效的内存操作。然而,在使用指针时需要小心,避免出现空指针和野指针的问题。希望这篇文章对你理解C语言中的指针部分有所帮助。
相关文章:
c语言进阶部分详解(指针初阶)
大家好!,前段时间一直在准备数学建模竞赛,现在也是忙完了。抓紧继续给大家带来c语言的内容。今天给大家带来指针初阶部分的讲解 当我们谈论C语言中的指针时,实际上是在讨论一种非常重要的概念,因为指针是C语言的核心之…...
Socks5代理IP在跨境电商与网络游戏中的网络安全应用
在数字化时代,跨境电商和网络游戏已成为全球网络世界中的两大热门领域。然而,这两者都面临着相似的网络安全挑战,需要高效的网络代理来解决。本文将讨论Socks5代理IP在跨境电商和网络游戏中的关键作用,以及如何通过这一技术增强网…...
Gin框架---基础综述
目录 一:经典入门案例二:请求参数2.1: API参数2.2: URL参数2.3: 表单参数 三: 响应参数四:数据解析和绑定4.1: JSON数据解析绑定4.2: FROM表单数据解析和绑定 五: 路由组六:异步处理七:中间件7.…...
排序算法-快速排序
属性 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元 素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有 …...
【Spring容器的启动过程】
Spring容器的启动过程 Spring 在初始化过程中有二个非常重要的步骤,容器的初始化与刷新。 初始化流程 如果想生成 bean 对象,那么就需要一个 beanFactory 工厂(DefaultListableBeanFactory)如果想让加了特定注解(如 …...
普通二本+转专业学计算机是什么感受
目录 自我介绍转入前为什么转专业为什么转入机械专业 转入后转入后感受确定自学计算机自学计算机的时间分配 自我介绍 作者现在是大二,由于当时高考考砸了,分数在重本线左右,为了去一个稍微好一点的学校,于是填报了化学工程与工艺(并不是说这专业不好,只是填报化工更容易进这个…...
力扣1、两数之和
转到力扣 题目 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可…...
一百七十三、Flume——Flume写入HDFS后的诸多小文件问题
一、目的 在用Flume采集Kafka中的数据写入HDFS后,发现写入HDFS的不是每天一个文件,而是一个文件夹,里面有很多小文件,浪费namenode的宝贵资源 二、Flume的配置文件优化(参考了其他博文) (一&a…...
Android.mk中C++使用
参考: https://gerrit.twrp.me/c/android_bootable_recovery//4366/1/Android.mk ifeq ($(BOARD_USES_RECOVERY_AS_BOOT), true) LOCAL_CFLAGS -DBOARD_USES_RECOVERY_AS_BOOT endif ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE), true) LOCAL_CFLAGS -DBOA…...
K8S:Pod概念、分类及相关的策略
文章目录 一.pod相关概念1.Pod基础概念2.Kubrenetes集群中Pod两种使用方式3.pause容器的Pod中的所有容器共享的资源4.kubernetes中的pause容器主要为每个容器提供功能:5.Kubernetes设计这样的Pod概念和特殊…...
【Java杂谈】#1 【MCA JAVA后端架构师】
文章目录 巧用弱引用 解决 TreadLocal内存泄漏问题P5,P6,P7Spring 巧用弱引用 解决 TreadLocal内存泄漏问题 < Treadlocal > 本地调用框架使用(Spring) IOC,AOP注解transactional,自动支持事务处理…...
Vue3路由
文章目录 Vue3路由1. 载入vue-router 库2. 实例2.1 Vue.js vue-router 实现单页应用2.2 router-link创建链接2.3 router-view显示与url对应组件2.4 <router-link> 相关属性 Vue3路由 1. 载入vue-router 库 Vue.js 路由需要载入vue-router 库 安装直接下载地址…...
Android Studio的笔记--aidl实现和调用
android AIDL接口使用 aidl实现新建aidl实现工程build.gradleproguard-rules.pro增加aidl文件 增加aidl实现aidl实现服务打开aidl服务 aidl使用新建aidl使用工程增加aidl文件使用aidl方法 相关回显 aidl实现 新建aidl实现工程 新建一个工程。工程名testaidl。包名com.lxh.tes…...
大模型从入门到应用——LangChain:代理(Agents)-[工具包(Toolkit)]
分类目录:《大模型从入门到应用》总目录 工具包是工具的集合,这些工具被设计成一起用于特定的任务,并且具有方便的加载方法。常见的工具包如下: CSV代理JiraJSON代理OpenAPI代理自然语言APIPandas数据框架代理PlayWright浏览器工…...
VR全景算不算好的创业项目?有哪些特性?
现在是全民创业的时代,大家都在找创业项目,那么什么是好的创业项目呢?有人会问VR全景算不算创业好项目呢?一般情况下好的创业项目,发展前景和市场消费群体都是比较大的,市场需求大才能满足多数消费者的需求…...
Spring系列文章:Spring集成Log4j2⽇志框架、整合JUnit
一、集成Log4j2⽇志框架 从Spring5之后,Spring框架⽀持集成的⽇志框架是Log4j2.如何启⽤⽇志框架: 第⼀步:引⼊Log4j2的依赖 <!--log4j2的依赖--> <dependency><groupId>org.apache.logging.log4j</groupId><a…...
flink的网络缓冲区
背景 在flink的taskmanager进行数据交互的过程中,网络缓冲区是一个可以提升网络交换速度的设计,此外,flink还通过网络缓冲区实现其基于信用值credit的流量控制,以便尽可能的处理数据倾斜问题 网络缓冲区 在flink中每个taskmana…...
产品经理学习笔记
产品文档之BRD、MRD和PRD - 知乎BRD、MRD和PRD一起被认为是从市场到产品需要形成的标准规范文档: 1、BRD(Business Requirement Document),商业需求文档,是一份产品商业论证报告,基于商业目标或价值所描述的…...
【深入理解Linux锁机制】七、互斥体
系列文章: 我的圈子:高级工程师聚集地 【深入理解Linux锁机制】一、内核锁的由来 【深入理解Linux锁机制】二、中断屏蔽 【深入理解Linux锁机制】三、原子操作 【深入理解Linux锁机制】四、自旋锁 【深入理解Linux锁机制】五、衍生自旋锁 【深入理解Linux锁机制】六、信…...
UGUI画布加载优化
在Unity中,UGUI画布的加载优化可以通过以下几种方式来实现: 1. 合理使用画布渲染模式:UGUI画布有三种渲染模式,分别是Screen Space - Overlay、Screen Space - Camera和World Space。在使用时,应根据场景需求选择最适…...
SEC的下一步目标是什么?过时的证券法与加密货币行业,哪个会被先淘汰?
加密货币已经“不合规”了,尤其是其“商业模式”,至少美国证券交易委员会(SEC)主席Gary Gensler这样认为。由于这种观点在美国监管机构中普遍存在,因此涉及加密的执法行动达到历史最高水平也不足为奇。 在短短几年内,我们目睹了所…...
Kafka3.0.0版本——消费者(独立消费者消费某一个主题数据案例__订阅主题)
目录 一、独立消费者消费某一个主题数据案例1.1、案例需求1.2、案例代码1.3、测试 一、独立消费者消费某一个主题数据案例 1.1、案例需求 创建一个独立消费者,消费firstTopic主题中数据,所下图所示: 注意:在消费者 API 代码中必…...
笔记本多拓展出一个屏幕
一、首先要知道,自己的电脑有没有Type-c接口,支持不支持VGA 推荐: 自己不清楚,问客服,勤问。 二、显示屏与笔记本相连,通过VGA 三、连接好了,需要去配置 网址:凑合着看ÿ…...
Redis 高可用及持久化
Redis 高可用 在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。但是在Redis语境中,高可用的含义似乎要宽泛一些,除了保证提供…...
Java高级: 反射
目录 反射反射概述反射获取类的字节码反射获取类的构造器反射获取构造器的作用反射获取成员变量&使用反射获取成员方法反射获取成员方法的作用 反射的应用案例 接下来我们学习的反射、动态代理、注解等知识点,在以后开发中极少用到,这些技术都是以后…...
【计算机网络】什么是WebSocket?
目录 WebSocket简介协议优点使用场景 WebSocket WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信,位于OSI模型的应用层。 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务器主动向客户端推送数据。在WebSocket API中&a…...
Apinto 网关: Go语言实现 HTTP 转 gRPC
gRPC 是由 Google 开发的一个高性能、通用的开源RPC框架,主要面向移动应用开发且基于 HTTP/2 协议标准而设计,同时支持大多数流行的编程语言。 gRPC 基于 HTTP/2 协议传输, HTTP/2 相比 HTTP1.x有以下优势: 采用二进制格式传输协议ÿ…...
【管理运筹学】第 7 章 | 图与网络分析(4,最大流问题)
系列文章目录 【管理运筹学】第 7 章 | 图与网络分析(1,图论背景以及基本概念、术语、矩阵表示) 【管理运筹学】第 7 章 | 图与网络分析(2,最小支撑树问题) 【管理运筹学】第 7 章 | 图与网络分析…...
linux学习总结
shell 1.在文本环境下,shell作为命令解释器,建立了用户和操作系统之间的接口。当用户键入一个命令时,shell将对该命令进行解释,并调用相应的程序。2.Linux下有多个shell,最常用的3个shell: bash tcsh zsh3.shell …...
【API 管理】什么是 API 管理,为什么它很重要?
当今复杂的数字生态系统由许多相互关联的部分组成。API 作为看门人和连接器在其中发挥着关键作用——提供了许多最终用户甚至没有注意到的自动化机会和效率。 企业密切关注 API。它们对于应用程序、数据和各种客户交互的功能至关重要。 这使得 API 管理成为几乎每个部门的组织…...
盘锦网站建设多少钱/谷歌seo技巧
argparse import argparse import time parser argparse.ArgumentParser() parser.add_argument("path") args parser.parse_args() print(args.path) time.sleep(3) CD到文件目录 python 文件名.py 参数参数值 pyinstaller pyinstaller打包python程序为exe程序…...
wordpress带支付宝主题/网址导航下载到桌面
华北电力大学2017年9月计算机等级考试时间华北电力大学简称华北电力或华电,创建于1958年,原名北京电力学院,下面给大家整理了华北电力大学2017年9月计算机等级考试时间,欢迎阅读!华北电力大学2017年9月计算机等级考试时间考试时间…...
小白的博客 wordpress/网站关键词怎么优化到首页
k8s管理 转载于:https://www.cnblogs.com/easonscx/p/10769739.html...
2022年网页游戏排行榜/网站seo优化网站
线程和进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作则是程序员。协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程&am…...
武汉模板网站制作/整站优化是什么意思
Django模板系统学习网站 https://www.runoob.com/django/django-template.html...
在线购物系统的分析与设计/淄博seo公司
高速读取与写入采用RAID01模式,高速读取与低速写入采用RAID5模式。 RAID01模式磁盘利用率只有50%,最大容量=磁盘数Nx 磁盘容量/2 ;数据读写速率是组RAID01的硬盘个数N/2*单个较慢硬盘的读写速率(N>4,且N…...