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

C语言学习笔记——指针(初阶)

前言

       指针可以说是C语言基础语法中最难的理解的知识之一,很多新手(包括我)刚接触指针时都觉得很难。在我之前发布的笔记中都穿插运用了指针,但是我一直没有专门出一期指针的笔记,这是因为我确实还有些细节至今还不太清楚。本篇将分享我对指针的理解,欢迎各位大佬批评指正。


一、指针是什么?       

       我们平常所说的指针其实就是指针变量是一种用来存放地址的变量。地址就是某一变量或函数的地址,当我们需要调用某一变量或函数时,可以通过该变量或函数的地址找到并调用。因此,当指针变量中存放了一个变量的地址时,我们就可以通过该指针找到其所指向的变量。

       就像在现实当中,我们知道一个朋友家的地址,才能找到这个朋友的家。

  在32位系统上,所有指针变量的大小均为4字节。在64位系统上为8字节。

二、常见的指针类型 

       常见指针类型可以和常见的数据类型一一对应,例如整型指针对应整型,浮点型指针对应浮点型。需要注意的是,结构体变量的数据类型为“struct + 结构体名”,定义结构体指针时需要将类型写全。

int* pi = NULL; //整型指针
char* pch = NULL; //字符型指针
float* pf = NULL; //単精度浮点型指针
double* plf = NULL; //双精度浮点型指针
sturct stru* ps = NULL; //结构体指针
FILE* pF = NULL;//文件指针
void (*test)() ptest = NULL; //函数指针

       上图即各种常见的指针类型的定义方式,例如 " pi " 为 " int* " 类型的指针(变量pi的数据类型为" int* "),即整型指针、" ps " 为 " struct stru* " 类型的指针,即该结构体类型的指针,而 " ptest " 为 " void (*)() " 类型的函数指针。

       图中的所有的指针均被初始化为NULL。NULL为空指针,其数值为0。

三、野指针 

       野指针就是指向未知地址的指针。

       当我们定义了一个指针变量后,如果不直接初始化为所需存放的地址,则应初始化为空指针NULL。否则该指针将会成为野指针。

       野指针有什么危害呢?当我们创建一个变量时,编译器会向内存申请一块空间来存放该变量,这块空间为合法空间,我们使用指针访问该空间即为合法访问。而野指针指向的随机地址可能并非合法空间,当我们使用野指针时就会产生非法访问。

       因此,当我们创建一个指针变量后,如果不要立即使用,则最好将其初始化为空指针,以避免造成非法访问。

四、指针的基本用法 

1. 指针的赋值和解引用

       当我们创建一个指针变量后,我们应该如何使用该指针变量来存储一个对应数据类型的数据呢?又该如何使用该指针来找到其所指向的数据呢?这里以整型指针为例。我们来看看以下代码,printf函数的打印值为多少呢?

int main()
{int a = 10;int* pa = &a;int b = *pa;printf("%d\n",b);return 0;
}

首先介绍一下上方代码出现的两种操作符:

1、取地址操作符 "&" :用来取出变量的地址,例如&a的值就是a的地址。

2、解引用操作符 " * " :用来解引用指针变量,使用指针所指向的数据,例如*pa的值即为a的值。这里需要注意区分 " int* " 中的 * 和解引用操作符 " * ",前者" int* "为一个整体,代表一种数据类型,而后者为一种操作符。

我们来逐条分析上方代码。

       第一行,定义变量a并初始化为10。第二行,定义指针变量pa,并初始化为a的地址。第三行,定义变量b,并初始化为pa所指向的变量,即b被初始化为10。因此printf函数打印的值为10。

2. 函数传参

       函数传参分为传值调用传址调用两种。传值调用指直接将变量传给函数,而传址调用则是将变量的地址传给函数。这里我通过一个简单的函数来介绍这两种传参方式的区别。

2.1 传值调用

       如图为一段传值调用的代码,我们将x初始化为0,并将x,10作为参数x,y传入test函数,在test函数中,x被赋值为y,那么为什么最后printf函数打印出来的x值为0呢?

       首先我们要明白一点,main函数中的x与test函数中的x不是同一个变量,因此test函数中的x被赋值为10并不会影响main函数中的x的值,main函数中的x也就还是0。

       如果我们希望使用传值调用实现上述逻辑,应对代码进行如下修改。

        通过函数返回值的方式对main函数中的x进行赋值即可。

2.2 传址调用

        这段代码与传值调用的第一段代码类似,将test函数参数中的(int)x换成了(int*)px。在test函数中,通过解引用px的方式找到x,并进行赋值操作,这样操作又可以实现上述逻辑,这是为什么呢?

       首先我们要搞清楚一点,每个变量被创建出来时都会占用一部分内存空间,在该变量被销毁之前,其占用的空间是不变的。当我们拥有该变量的地址时,我们可以在它未被销毁的任何位置通过其地址找到该变量。

       在上面这段代码中,main函数中的x在main函数结束时才被销毁,那么在main函数调用test函数时,x并未被销毁,因此在test函数中,我们可以通过x的地址px找到并给x赋值。

2.3 用法总结 

          传值调用和传址调用不分绝对的好坏,需要根据实际情况选用不同的方式。

当不需要改变参数值,只需要调用参数参与函数运算时,多使用传值调用

当需要改变参数值时,多使用传址调用

五、指针运算 

       指针运算的知识多用于与数组结合的问题。

1. 指针 +(-) 整数

       这段代码分别打印了p-1、p和p+1(地址的格式符为%p,打印值为十六进制)。我们可以发现,指针通过加减整数得到的值仍然为指针

       在此图中,指针+1,地址+4。这是因为图中的指针为整型指针(int*),一个整型的大小为4个字节,指针+1的含义是跳过一个整型,也就是跳过4个字节,即地址+4。同理,如果是一个字符指针(char*)+1,则跳过一个字节,地址+1;如果是双精度浮点型指针(double*)+1,则跳过八个字节,地址+8。

2. 指针 - 指针

       根据上述指针+(-)整数的知识,我们可以推出,指针-指针的值应该为整数。

       这里我通过字符指针为例(字符指针每次+1跳过一个字节,更加直观)。上图中,pa为低地址,pb为高地址,差值为32。pa-pb为低地址-高地址,结果为负的差值,即-32,同理,pb-pa则为32。

 六、二级指针

       我们知道,一个整型指针(int*)可以存储一个整型(int)变量的地址。那么作为一个指针变量,我们同样可以使用一个指针来存储它的地址。

        我们来逐一分析上方代码。首先pa为指向a的指针,它的类型为整型指针(int*),而ppa为指向pa的指针,它的类型为整型指针指针(int**)。这就是所谓的二级指针。我们同样可以通过二级指针找到最终的变量值。首先进行一次解引用找到其所指向的一级指针,再次解引用即可得到变量值,如图中" **ppa "。

        当然,有二级指针,同样也有三级,四级甚至更高级数的指针,它们的底层逻辑与二级指针相同,这里就不过多解释了。


结束语

       以上就是有关于指针的基础内容了,希望能够帮助到正在学习C语言的同学们。如果文章内容有错误或知识点有遗漏,望各位大佬批评或补充在评论区或私信。

相关文章:

C语言学习笔记——指针(初阶)

前言 指针可以说是C语言基础语法中最难的理解的知识之一,很多新手(包括我)刚接触指针时都觉得很难。在我之前发布的笔记中都穿插运用了指针,但是我一直没有专门出一期指针的笔记,这是因为我确实还有些细节至今还不太清…...

阿赵的MaxScript学习笔记分享十二《获取和导出各种数据》

大家好,我是阿赵,周日的早上继续分享MaxScript学习笔记,这是第十二篇,获取和导出各种数据 1、导出数据的目的 使用3DsMax建立3D模型后,很多时候需要输出模型到别的引擎去使用,常用的格式有Obj、FBX、SLT等…...

react-draggable实现拖拽详解

react-draggable属性常用属性属性列表事件列表举例首先安装 react-draggable实现移动希望小编写的能够帮助到你😘属性 常用属性 属性默认值介绍axisxhandle拖动的方向,可选值 x ,y,bothhandle无指定拖动handle的classposition无handle的位置&#xff0…...

01.进程和线程的区别

进程和线程的区别进程和线程是计算机中的两个核心概念,它们都是用来实现并发执行的方式,但是它们在实现并发的方式和资源管理方面有一些重要的区别。进程是一个程序的运行实例。每个进程都有自己的内存空间、代码、数据和系统资源(如文件描述…...

逻辑优化-rewrite

简介 逻辑综合中的rewrite算法是一种常见的优化算法,其主要作用是通过对逻辑电路的布尔函数进行等效变换,从而达到优化电路面积、时序和功耗等目的。本文将对rewrite算法进行详细介绍,并附带Verilog代码示例。 一、算法原理 rewrite算法的…...

文件传输与聊天系统设计

技术:Java等摘要:本文介绍了一种基于TCP/IP协议使用Socket技术实现的聊天室系统,包括私聊功能和文件传输功能,对系统的主要模块进行了分析,并对系统实现过程中遇到的关键性技术进行了阐述,最后对系统进行了…...

蓝桥杯第十四届校内赛(第三期) C/C++ B组

一、填空题 (一)最小的十六进制 问题描述   请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。   请将这个数的十进制形式作…...

有关平方或高次方的公式整理一元高次方程的求解

Part.I Introduction 这篇博文记录一下数学中常用的有关平方或高次方的一些公式。 Chap.I 一些结论 下面一部分汇总了一些重要的结论 完全平方公式:(ab)2a22abb2(ab)^2a^22abb^2(ab)2a22abb2平方差公式:a2−b2(ab)(a−b)a^2-b^2(ab)(a-b)a2−b2(ab)(…...

Java笔记3

ArrayListArrayList<String> list new Arraylist<>();<>是泛型表示存放的数据类型&#xff0c;注意不能是基本数据类型&#xff1b;增删改查增&#xff1a;add 返回值为true删&#xff1a;remove 1.直接删元素2.根据索引删元素改&#xff1a;set&#xff08…...

Leetcode.2202 K 次操作后最大化顶端元素

题目链接 Leetcode.2202 K 次操作后最大化顶端元素 Rating &#xff1a; 1717 题目描述 给你一个下标从 0开始的整数数组 nums&#xff0c;它表示一个 栈 &#xff0c;其中 nums[0]是栈顶的元素。 每一次操作中&#xff0c;你可以执行以下操作 之一 &#xff1a; 如果栈非空…...

JAVA知识点全面总结3:String类的学习

三.String类学习 1.String&#xff0c;StringBuffer&#xff0c;StringBuilder的区别&#xff1f; 2.字符串拼接用加号的原理 &#xff1f; 3.字符串常量池如何理解&#xff1f; 4.String的intern方法理解&#xff1f; 5.String的equals方法和compareTo方法的使用&#xf…...

Eureka注册中心和Nacos注册中心详解以及Nacos与Eureka有什么区别?

目录&#xff1a;前言Eureka注册中心Nacos注册中心Nacos与Eureka有什么区别&#xff1f;前言提供接口给其它微服务调用的微服务叫做服务提供者&#xff0c;而调用其它微服务提供的接口的微服务则是服务消费者。如果服务A调用了服务B&#xff0c;而服务B又调用了服务C&#xff0…...

Web3D发展趋势以及Web3D应用场景

1&#xff0c;Web3D发展趋势随着互联网的快速发展&#xff0c;Web3D技术也日渐成熟&#xff0c;未来发展趋势也值得关注。以下是Web3D未来发展趋势的七个方面&#xff1a;可视化和可交互性的增强&#xff1a;Web3D可以为三维数据提供可视化和可交互性的增强&#xff0c;将极大地…...

2023-3-4 刷题情况

按位与为零的三元组 题目描述 给你一个整数数组 nums &#xff0c;返回其中 按位与三元组 的数目。 按位与三元组 是由下标 (i, j, k) 组成的三元组&#xff0c;并满足下述全部条件&#xff1a; 0 < i < nums.length 0 < j < nums.length 0 < k < nums.l…...

前端面试总结

1.引言 最近参加了大量的招聘会&#xff0c;投递了大量的简历&#xff0c;整整体会了从“随便找个厂上一下”——“还是的找个大厂”——“没人要”——“急了急了,海投一波”——“工资有点尬”——“海投中…”。简单说一下自己的一些感受吧&#xff0c;现在的前端属实有点尴…...

Geospatial Data Science (6): Spatial clustering

Geospatial Data Science (6): Spatial clustering 1.Clustering, spatial clustering, and geodemographics 本节涉及空间观测的统计聚类。许多问题和主题都是复杂的现象,涉及多个维度,难以归纳为一个单一的变量。在统计学术语中,我们把这一类问题称为多变量,而不是在…...

蚁群算法优化问题

%%%%%%%%%%%%蚁群算法解决 TSP 问题%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%% clear all; %清除所有变量 close all; %清图 clc; %清屏 m 50; %蚂蚁个数 Alpha 1; %信息素重要程度参数 Beta 5; %启发式因子重要程度参数 Rho 0.1; %信息素蒸发系数 G 20…...

为啥一个 main 方法就能启动项目

在 Spring Boot 出现之前&#xff0c;我们要运行一个 Java Web 应用&#xff0c;首先需要有一个 Web 容器&#xff08;例如 Tomcat 或 Jetty&#xff09;&#xff0c;然后将我们的 Web 应用打包后放到容器的相应目录下&#xff0c;最后再启动容器。 在 IDE 中也需要对 Web 容器…...

洛谷:P1554 梦中的统计 JAVA

思路&#xff1a;定义一个长度为10的数组&#xff0c;数组下标代表数组元素的数字&#xff0c;比如arr[0]代表数字0.用一个for循环&#xff0c;对每个数先取余再取整&#xff0c;知道取整得到的数为0&#xff0c;说明该数字已经被拆解完了。今天又学了一个输入&#xff0c;原来…...

C++初学笔记整理

目录 1. C关键字 2. 命名空间 1&#xff09;命名空间的引入和概述 2&#xff09;命名空间的定义 3&#xff09;std与命名空间的使用 4).相关特性 3. C输入&输出 4. 缺省参数 1 &#xff09;缺省参数概念 2&#xff09;使用及分类 a.全缺省 b.部分缺省 5. 函数…...

记录--在Vue3这样子写页面更快更高效

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 在开发管理后台过程中&#xff0c;一定会遇到不少了增删改查页面&#xff0c;而这些页面的逻辑大多都是相同的&#xff0c;如获取列表数据&#xff0c;分页&#xff0c;筛选功能这些基本功能。而…...

【程序设计与算法(三)】测验和作业题部分答案汇总(面向对象篇)

题目来源&#xff1a;程序设计与算法&#xff08;三&#xff09;测验和作业题汇总 文章目录001:简单的swap002:难一点的swap003:好怪异的返回值004:神秘的数组初始化005:编程填空&#xff1a;学生信息处理程序006:奇怪的类复制007:返回什么才好呢008:超简单的复数类009:哪来的输…...

LeetCode 349. 两个数组的交集和 692. 前K个高频单词

两个数组的交集 难度 简单 题目链接 这道题的难度不大&#xff0c;我们可以把数组里的数据存到set里面。这样就完成了排序和去重&#xff0c;然后我们再把一个set里面的数据和另外一个set数据进行比较。如果相同就插入到数组里。 代码如下&#xff1a; 但是这个算法的时间复…...

SpringCloud的五大组件功能

SpringCloud的五大组件 EurekaRibbonHystrixZuulConfig 一、Eureka 作用是实现服务治理&#xff0c;即服务注册与发现。 Eureka服务器相当于一个中介&#xff0c;负责管理、记录服务提供者的信息。服务调用者不需要自己寻找服务 &#xff0c;而是把需求告诉Eureka &#x…...

剑指 Offer II 016. 不含重复字符的最长子字符串

题目链接 剑指 Offer II 016. 不含重复字符的最长子字符串 mid 题目描述 给定一个字符串 s&#xff0c;请你找出其中不含有重复字符的 最长连续子字符串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子字符串是 “abc”&#xff0c;所以其长度…...

HBase读取流程详解

读流程从头到尾可以分为如下4个步骤&#xff1a;Client-Server读取交互逻辑&#xff0c;Server端Scan框架体系&#xff0c;过滤淘汰不符合查询条件的HFile&#xff0c;从HFile中读取待查找Key。其中Client-Server交互逻辑主要介绍HBase客户端在整个scan请求的过程中是如何与服务…...

Redis学习(一):NoSQL概述

为什么要使用Nosql 现在是大数据时代&#xff0c;过大的数据一般的数据库无法进行分析处理了。 单机MySQL的年代 90年代&#xff0c;一个基本的网站访问量一般不会太大&#xff0c;单个数据库完全足够&#xff01; 那个时候&#xff0c;更多的去使用静态网站&#xff0c;服务器…...

ESP32设备驱动-MCP23017并行IO扩展驱动

MCP23017并行IO扩展驱动 1、MCP23017介绍 MCP23017是一个用于 I2C 总线应用的 16 位通用并行 I/O 端口扩展器。 16 位 I/O 端口在功能上由两个 8 位端口(PORTA 和 PORTB)组成。 MCP23017 可配置为在 8 位或 16 位模式下工作。 其引脚排列如下: MCP23017 在 3.3v 下工作正常…...

RabbitMQ简介

0. 学习目标 能够说出什么是消息中间件能够安装RabbitMQ能够编写RabbitMQ的入门程序能够说出RabbitMQ的5种模式特征能够使用Spring整合RabbitMQ 1. 消息中间件概述 1.1. 什么是消息中间件 MQ全称为Message Queue&#xff0c;消息队列是应用程序和应用程序之间的通信方法。是…...

【项目设计】高并发内存池(五)[释放内存流程及调通]

&#x1f387;C学习历程&#xff1a;入门 博客主页&#xff1a;一起去看日落吗持续分享博主的C学习历程博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 也许你现在做的事情&#xff0c;暂时看不到成果&#xff0c;但不要忘记&…...