C语言入门系列:探秘二级指针与多级指针的奇妙世界

文章目录

  • 一,指针的回忆杀
    • 1,指针的概念
    • 2,指针的声明和赋值
    • 3,指针的使用
      • 3.1 直接给指针变量赋值
      • 3.2 通过*运算符读写指针指向的内存
        • 3.2.1 读
        • 3.2.2 写
  • 二,二级指针详解
    • 1,定义
    • 2,示例说明
    • 3,二级指针与一级指针、普通变量的关系
      • 3.1,与一级指针的关系
      • 3.2,与普通变量的关系,
      • 示例说明
    • 4,二级指针的常见用途
    • 5,二级指针扩展到多级指针
  • 小结

C语言的学习之旅中,二级指针乃至多级指针往往是初学者感到“恶心”却又不得不面对的重要概念。

不过,一旦掌握了它们的精髓,你会发现它们其实并不那么可怕,反而在某些高级应用中显得尤为强大和灵活。

一,指针的回忆杀

1,指针的概念

指针就是内存地址,内存地址指向内存中的一个单元,这个单元就像一个个小房间,里面住着某种数据,可能是整数,可能是浮点数,可能是字符,也可能是另一个指针。

为了方便理解和记忆,可以把指针当作酒店房间号。

指针作为一种特殊的数据,也需要存储在内存中。

2,指针的声明和赋值

C语言通过指针变量为指针开辟一块内存。

int num = 10;
int* p;
p = #

如上代码,定义了指针变量p,声明变量时如果带有*号,说明这个变量是指针变量。

这个*号的作用是告诉编译器,这个指针变量p要存储的是变量num的值的内存地址,这个内存地址从形式上看也没什么特别,就是一个整数。

上面的代码中p = #,通过地址运算符&取出变量num的地址,赋给指针变量p

在这里插入图片描述

3,指针的使用

3.1 直接给指针变量赋值

上面的代码中p = # 所示,可以和普通变量一样,直接给指针变量赋值,只是这个值代表的是内存地址而已。

3.2 通过*运算符读写指针指向的内存

3.2.1 读

我们还可以通过* 运算符操作指针指向的内存中的值。

int num = 10;
int* p;
p = #int num2 = *p;

如上代码最后一行int num2 = *p;,运算符*的作用是告诉编译器,找到指针p指向的地址,从中读取数据。

3.2.2 写

当然,可以修改指针指向的内存中的数据。

int num = 10;
int* p;
p = #*p = 100;

上述代码*p = 100;,将指针p指向的内存中数据的值修改为100。注意,此时num的值也变为100了,原因是修改的就是num的内存中的值。

二,二级指针详解

1,定义

二级指针,顾名思义,是指向指针的指针,即一个变量,其类型是指向指针的地址。在C语言中,声明一个二级指针的基本形式如下:

数据类型** pointerName;

这里,**pointerName表示pointerName是一个指向指针的指针,它存储的是一个指针变量的地址。

int num = 10;
int* p;
p = #int** pp = &p;

如上,二级指针变量pp指向的是指针变量p的地址。
在这里插入图片描述

如上图所示,发现二级指针需要跳2级才能获取普通变量内存中的值,这也是二级指针名称的来源。

2,示例说明

以一个整型变量为例:

int a = 12;
int *p = &a;
int **pp = &p;

根据上述定义,我们可以得出以下计算结果:

p == &a
*p == 12
pp == &p
*pp == p
**pp == a

**pp就是获取a变量的值,因为pp指向的是p的地址,而p指向的又是a的地址,所以 **pp 就相当于a

3,二级指针与一级指针、普通变量的关系

3.1,与一级指针的关系

一级指针存储的是普通变量的地址,而二级指针存储的是一级指针的地址。
通过二级指针,我们可以间接访问到一级指针所指向的数据,实现更深层次的间接访问。

3.2,与普通变量的关系,

普通变量是数据存储的最直接形式,通过一级指针,我们增加了一层间接访问;二级指针则在此基础上再增加一层间接性,使得对普通变量的操作更为灵活。

示例说明

#include <stdio.h>
#include <stdlib.h>int main() {int value = 10;int *p = &value; // 一级指针,指向valueint **pp = &p;   // 二级指针,指向一级指针pprintf("Value: %d\n", value);      // 直接访问printf("Value via *p: %d\n", *p);  // 通过一级指针访问printf("Value via **pp: %d\n", **pp); // 通过二级指针访问return 0;
}

此例中,value是一个普通整型变量,p是一级指针指向value,而pp作为二级指针,则指向p。通过**pp,我们依然能最终访问到value的值,展示了指针间接访问的层级关系。

4,二级指针的常见用途

  • 动态内存管理:在动态分配数组时,可以使用二级指针来存储数组的首地址,便于管理和释放内存。
  • 函数参数传递:当希望函数能够修改外部指针变量(而非指针所指向的内容)时,需使用二级指针作为函数参数。
  • 指向指针的指针运算:在复杂数据结构操作中,二级指针提供了对指针进行指针运算的能力,如链表的节点交换、树结构的遍历等。

5,二级指针扩展到多级指针

多级指针的概念基于二级指针进一步扩展,即指针的指针的指针……依此类推。

一句话,多级指针存储的是上一级指针的地址。

虽然在日常编程中较为罕见,但在特定场景下,如复杂的内存管理、高度抽象的数据结构设计或底层系统编程中,多级指针可以提供极大的灵活性。

示例:三级指针

#include <stdio.h>void printViaTriplePointer(int ***triplePtr) {printf("Value via ***triplePtr: %d\n", ***triplePtr);
}int main() {int value = 7;int *p = &value;int **pp = &p;int ***triplePtr = &pp;printViaTriplePointer(triplePtr);return 0;
}

这个例子中,triplePtr是一个三级指针,通过它我们依然能够最终访问到最初定义的value。虽然看起来繁琐,但在特定逻辑或系统级操作中,这样的间接访问机制可能非常有用。

小结

总之,二级指针乃至多级指针虽初看复杂,实则是C语言中处理复杂数据结构和内存管理的强大工具。通过实践和理解,你将逐步揭开它们的神秘面纱,发现其背后的逻辑之美。

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

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

相关文章

Python爬虫-贝壳新房

前言 本文是该专栏的第32篇,后面会持续分享python爬虫干货知识,记得关注。 本文以某房网为例,如下图所示,采集对应城市的新房房源数据。具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。接下来,跟着笔者直接往下看正文详细内容。(附带完整代码) 正文 地…

北京智慧养老平台app打造,智慧养老,安心享老

目前&#xff0c;我国60岁以上老年人占人口比重已超过21%&#xff0c;我国老年人口数量快速增长&#xff0c;人口老龄化程度不断加深。与此同时&#xff0c;老年人的养老需求也在逐步上升。除了日常吃穿等生活需求外&#xff0c;他们在健康、精神方面也提出来新的要求。为了满足…

高职人工智能专业实训课之“自然语言处理”

一、前言 在人工智能领域&#xff0c;自然语言处理&#xff08;NLP&#xff09;技术日益成为研究和应用的热点。为了满足高职院校对NLP专业实训课程的需求&#xff0c;唯众人工智能教学实训凭借其前沿的教育技术平台&#xff0c;特别是GPU虚拟化技术&#xff0c;为学生提供了高…

【R语言】对一个Plot绘制多个图,并且每个图单元也包含多个图

以一个Plot绘制五行六列共30个图&#xff0c;然后每30个图单元包含两个图为例&#xff1a; 如下图所示&#xff1a; 代码如下&#xff1a; for (i in 1:(5*6)) {create_subplots <- function() {library(ggplot2)library(dplyr)library(tidyr)# 创建一个随机的数据框simula…

linux系统指令查漏补缺

目录 一.磁盘操作 二.lvm 三.top 4.nohup 一.磁盘操作 1. lsblk -f 显示磁盘和它的相关内容 2.tuen2fs -c -1 /dev/sdx 关闭某个磁盘的自检 3.修改配置&#xff0c;使文件系统不要开机自检 cat /etc/fstab 全0表示开机不自检 全1表示开机自检 同时在这个文件中可添加…

sql资料库

1、distinct(关键词distinct用于返回唯一不同的值)&#xff1a;查询结果中去除重复行的关键字 select distinct(university) from user_profile select distinct university from user_profile distinct是紧跟在select后面的&#xff0c;不能在其他位置&#xff0c;不然就…

4、SpringMVC 实战小项目【加法计算器、用户登录、留言板、图书管理系统】

SpringMVC 实战小项目 3.1 加法计算器3.1.1 准备⼯作前端 3.1.2 约定前后端交互接⼝需求分析接⼝定义请求参数:响应数据: 3.1.3 服务器代码 3.2 ⽤⼾登录3.2.1 准备⼯作3.2.2 约定前后端交互接⼝3.2.3 实现服务器端代码 3.3 留⾔板实现服务器端代码 3.4 图书管理系统准备后端 3…

轻量级日志系统——Loki

目录 一、loki简介 二、Loki 快速上手 第一步安装 Loki 第二步安装 Promtail 第三步安装granafa 三、LogQL 语法 四、Loki收集nginx日志 1、修改nginx配置 2、nginx服务器上安装promtail 3、添加doshbarod 一、loki简介 Loki是 Grafana Labs 团队最新的开源项目&am…

RERCS系统开发实战案例-Part05 FPM Application的Feeder Class搜索组件的实施

1、通过事务码 SE24对Feeder Class实施 1&#xff09;接口页签的简单说明&#xff1a; ① IF_FPM_GUIBB&#xff1a;通用UI构建块&#xff0c;整个UIBB模块的基础接口&#xff1b; ② IF_FPM_GUIBB_SEARCH&#xff1a;通用搜索UI构建块&#xff0c;搜索组件UIBB的基础接口&…

中东文明史

转自&#xff1a;想要了解完整的中东文明史&#xff1f;这篇文章成全你 - 知乎 (zhihu.com) 写在前面 中东文明是人类历史上最古老的文明。人类祖先从东非大裂谷走出之后&#xff0c;首先选择定居在中东地区的新月沃土上&#xff0c;并建立了人类历史上有文字记载的第一个文明…

Mybatis-映射文件中select标签resultType属性的使用

数据库的最最基本操作“增删改查”&#xff0c;“查”是最复杂的&#xff0c;有各种各样的查询&#xff0c;所以对应到Mybatis中的select标签也是这四个操作中最复杂的 resultType属性的使用 1.返回的结果是List集合的类型 select标签里的resultType类型设置为List集合里的元…

关于正点原子stm32f103精英板v1的stlink通信失败问题解决方案

由于最新的固件不适配&#xff0c;我们要想其工作要下载007的固件。 https://www.st.com/en/development-tools/stsw-link007.html?dlredirect 版本选择最低的。然后选择windows文件夹&#xff0c;更新程序 然后进keil就能正常识别到了

mediasoup源码分析(三)channel创建及信令交互

mediasoup源码分析--channel创建及信令交互 概述跨职能图业务流程图代码剖析tips 概述 在golang实现mediasoup的tcp服务及channel通道一文中&#xff0c;已经介绍过信令服务中tcp和channel的创建&#xff0c;本文主要讲解c中mediasoup的channel创建&#xff0c;以及信令服务和…

【C++高阶】掌握AVL树:构建与维护平衡二叉搜索树的艺术

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;STL-> map与set &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀AVL树 &#x1f4d2;1. AVL树…

MySQL理解-下载-安装

MySQL理解: mysql:是一种关系型数据库管理系统。 下载&#xff1a; 进入官网MySQLhttps://www.mysql.com/ 找到download 滑动到最下方&#xff1a;有一个开源社区版的链接地址&#xff1a; 然后就下载完成了 安装&#xff1a; 双击&#xff1a; 一直next 一直next这一步&…

Spire.PDF for .NET【文档操作】演示:设置 PDF 文档的 XMP 元数据

XMP 是一种文件标签技术&#xff0c;可让您在内容创建过程中将元数据嵌入文件本身。借助支持 XMP 的应用程序&#xff0c;您的工作组可以以团队以及软件应用程序、硬件设备甚至文件格式易于理解的格式捕获有关项目的有意义的信息&#xff08;例如标题和说明、可搜索的关键字以及…

java基于ssm+jsp 美食推荐管理系统

1前台首页功能模块 美食推荐管理系统&#xff0c;在系统首页可以查看首页、热门美食、美食教程、美食店铺、美食社区、美食资讯、我的、跳转到后台等内容&#xff0c;如图1所示。 图1前台首页功能界面图 用户注册&#xff0c;在注册页面可以填写用户名、密码、姓名、联系电话等…

仓库管理系统01--数据库介绍

1、表结构 1&#xff09;UserInfo 用户表 2&#xff09;Supplier供应商表 3&#xff09;Store 仓库表 4&#xff09;其他表 Customer 客户表&#xff0c;Spec 规格表&#xff0c;GoodsType 货物类别表&#xff0c;Goods 货物表&#xff0c;InStore 入库表&#xff0c;OutSto…

LearnOpenGL - Android OpenGL ES 3.0 绘制纹理

系列文章目录 LearnOpenGL 笔记 - 入门 01 OpenGLLearnOpenGL 笔记 - 入门 02 创建窗口LearnOpenGL 笔记 - 入门 03 你好&#xff0c;窗口LearnOpenGL 笔记 - 入门 04 你好&#xff0c;三角形OpenGL - 如何理解 VAO 与 VBO 之间的关系LearnOpenGL - Android OpenGL ES 3.0 绘制…

有趣的 Oracle JDBC 驱动包命名问题 - ojdbc6 和 ojdbc14 哪个新?!

有趣的 Oracle JDBC 驱动包命名问题 - ojdbc6 和 ojdbc14 哪个新?! 1 背景概述 最近协助一个小兄弟排查了某作业使用 sqoop 采集 oracle 数据的失败问题&#xff0c;问题现象&#xff0c;问题原因和解决方法都挺直观&#xff0c;但在此过程中发现了一个有趣的 Oracle JDBC 驱…