指针进阶知识超详细讲解(C语言)(中)

news2025/1/16 4:48:57

前言
苦苦等待,终于迎来了我们的指针讲解第二期,如果有还没有看过上一期的小伙伴,那赶紧点击这个链接学习后再来看这篇博客吧。链接:指针基础知识超详细讲解(C 语言)(上)
如果对学习C语言有兴趣那千万不要忘记关注本专栏哦。O(∩_∩)O (也关注下博主吧!): C语言学习专栏

在这里插入图片描述

文章目录

  • 1,多级指针
  • 2,一维数组传参的本质和数组名的含义
  • 3,指针数组
  • 4,数组指针
  • 5,二维数组传参的本质
  • 6,尾声

上一篇博客我们学习了基本的指针类型,指针的加减运算,以及野指针的成因和避免野指针的方法。今天这一篇博客我们将进一步学习指针。那么久让我们开始吧!

1,多级指针

首先让我们写先一个简单的指针变量。
int a = 10;
int* pa =&a;
这里的int* 代表pa的数据类型是整形指针。那么这个呢?
int* * ppa = pa;
我们知道pa存的地址会指向整形变量a,所以我们用int类型来定义pa,如果我们要吧pa的地址在储存在一个指针变量中,那么我们就应该用int * *来定义ppa,int *指得意思是ppa存的地址指向的变量的数据类型就是int *类型的,之后的 *的意思是指ppa是个指针。
那么这么定义ppa的意思就是ppa是一个储存 数据类型为int 的变量的地址 的指针。
这个就是二级指针。
那我们再定义一个指针。
int
* * * pppa = ppa;
与上面同理,ppa就是一个三级指针,两级以上的指针就被我们称为多级指针。
我们知道从pa中取出a我们要解引用 * pa=a
那么我们要从ppa中取出a就要这样解引用 * ( * ppa)= * pa = a
pppa同理。

2,一维数组传参的本质和数组名的含义

假如这里有一个函数,它的参数是一个数组,我们要如何传递这个参数呢?可以看看下面的示范。

#include<stdio.h>
viod test(int arr[])
{
;
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
test(arr);
return 0;
}

我肯可以看到我们直接将数组名传到函数中了,这是个什么原理呢?接下来我来为大家介绍数组名的本质。
当arr单独存在时,它代表数组首元素的地址,我们将arr作为参数传过去实际上是把arr数组的首地址传了过去,那么这时候大家会疑惑?既然我传过去的是地址,为什么我要把参数设置为int arr[ ]呢?实际上int arr[ ]等价于int * arr也就是说,我们也可以把参数的格式写成int * arr。
但是也有特例的情况比如我们要打印数组大小的时候会写出这样一段代码。
printf(“%zd”,sizeof(arr));
此时arr也是单独存在的,但是这是他并不是数组首元素的地址,而是代表整个数组,除了这种情况以外,数组名单独出现都代表数组首元素的地址。
既然这样&arr代表着什么呢?我们不妨写下这么一段代码测试一下。

#include<stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
printf("%p %p",arr,&arr);
return 0;
}

在这里插入图片描述

我们会发现两者的地址是一样的难道&arr代表首元素的地址么?那我们对各自地址+1在打印看看。

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%p %p %p",arr, arr+1, &arr+1);
	return 0;
}

在这里插入图片描述
可以看出结果却不一样arr+1相较于arr多了4,刚好是一个整形的大小,而&arr+1比起arr缺多了整整40,正好是整个数组的大小。对&arr+1跳过了整个数组的大小。说明&arr是整个数组的地址。
既然arr单独出现时代表数组首元素的地址,那么我们对arr进行解引用,我们就会得到数组的首元素 。 * arr = 1
那个对arr+1解引用自然就是数组的第二个元素了 *arr+1 = 2
那么我们就会发现 * arr 与 arr[0]与 * arr+0是等价的, * arr+1与arr[1]是等价的。当我们想通过循环打印整个数组时我们就可以这么写。

for(int i = 0;i <= 9 ;i++)
{
printf("%d",*arr+i);
}

3,指针数组

指针数组,顾名思义是个数组,整形数组里面装的是整形,字符数组里装的是字符,那么指针数组里装的自然就是指针。最基本的整形指针数组是这样定义的(数组里的元素是整形指针)。
int* arr[10] ;(arr是数组名,数组中有十个元素)
我们可以在其中存入整形指针。

4,数组指针

数字指针,显然它是个指针,他储存的是一个数组的地址,我们先来定义一个整形数组指针(存的是整形数组的地址)来做个示范吧。
int arr[2]={1,2};
int ( * parr)[2] = &arr;([ ]的优先级高于*,所以要把*parr用括号()括起来表明parr是指针,[2]指该数组指针指向的数组有两个元素)
那么数组指针加减运算会有什么结果呢?

int main()
{
	int arr[4] = { 1,2,3,4 };
	int(*parr)[4] = &arr;
	printf("%p %p", parr, parr + 1);
	return 0;
}

在这里插入图片描述

我们会发现刚好+了16,正好是arr数组的大小,可见对parr+1会跳过整个数组的大小。
如果对parr解引用,那么我们就会得到数组arr的地址,即arr首元素的地址。

5,二维数组传参的本质

首先我们可以把二维数组理解为一个一维数组,而这个一维数组里面每一个元素都是一个一维数组,即二维数组的每一行都是他的一个元素。对arr解引用会得到其第一个元素的地址,即第一行的一维数组。对arr+1解引用则会得到第二行的一维数组的地址。
在这里插入图片描述

我们将二维数组传参是可以有着两种写法。

void test(int(*parr)[2])
void test (int arr[][2])//行数可以不写但是列数必须写

这两种写法是完全等价的,因为* parr = arr [ 0 ]= * arr+0 **parr = arr[0][0]=**arr.
对二维数组传参其实传的是二维数组第一行的地址。
*((*parr+1)+1)就等价于 arr[1][1]。

6,尾声

经过这篇博客,想必大家对数组和指针的了解有了进一步的加深,认为博主写的不错的千万不要忘记关注博主等待指针讲解(下),希望大家都能够学好指针(指针很重要),想着自己的目标再进一步!
最终期链接,冲冲冲!

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

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

相关文章

Leetcode1423. 可获得的最大点数

Every day a Leetcode 题目来源&#xff1a;1423. 可获得的最大点数 解法1&#xff1a;前缀和 后缀和 基于贪心的思想&#xff0c;要使得获得的点数最大&#xff0c;每次拿卡牌都应该选点数尽量高的卡牌。 但是拿卡牌有限制&#xff0c;每次行动&#xff0c;只可以从行的…

21、pytest参数化中标记单独的测试用例

官方实例 # content of test_expectation_xfail import pytestpytest.mark.parametrize("test_input, expected",[("35",8),("24",6),pytest.param("6*9",42,markspytest.mark.xfail)], ) def test_eval(test_input, expected):asser…

Linux基本指令(2.0)

周边知识&#xff1a; 1.Linux中&#xff0c; 一切皆文件 构建大文件 输入如下shell命令 i1; while [ $i -le 10000]; do echo "hello Linux $i"; let i; done 此时大文件已经创建在big.txt 此时我们发现cat查看无法查看开始内容 我们使用more 当占满一屏之后就不…

JavaScript <md5加密的两种不同输出结果分析>--案例(二点一)

前言: 问题是这样的,在浏览器中看到这段代码 然后在控制台进行输出.得到: 紧接着,就在,js文件里面进行转译: 可是,得到的结果是: 这是问题!!! 正题: 为什么相同的js代码,在 .js 文件中的输出与 Chrome 控制台中的输出不一样? 环境差异&#xff1a;不同的JavaScript环境&…

STM32F1中断NVIC

目录 1. 中断系统 2. 中断向量表 3. NVIC基本结构 4. NVIC优先级分组 5. NVIC程序编写 5.1 中断分组 5.2 中断结构体变量 5.3 中断通道选择 5.4 抢占优先级和响应优先级配置 6. 中断程序执行 1. 中断系统 中断&#xff1a;在主程序运行过程中&#xff0…

Java基础数据类型

Java有八种基础的数据类型&#xff0c;它们被分为两个主要的类别&#xff1a;原始类型和引用类型。原始类型又被分为四类&#xff1a;整型、浮点型、字符型和布尔型。 整型&#xff08;Integral Types&#xff09;&#xff1a; 这些类型用于存储整数。它们包括&#xff1a; ○…

七大经典高效学习方法

金字塔学习模型 金字塔学习是美国学习专家爱德加戴尔1946年提出的。 他将学习分为主动学习和被动学习两种类型&#xff0c;用数字形象地呈现了采用不同学习方式&#xff0c;学习者在两周后还能记住的内容有多少。 被动学习&#xff1a;通过听讲、阅读、视听、演示这些活动&a…

【Windows本地端口占用脚本自动化】

本地启动多个Java微服务&#xff0c;因为停电或者内存回收原因&#xff0c;IDEA直接退出&#xff1b;再次启动各个服务会提示端口占用。 每次都cmd输入命令手动Kill比较繁琐&#xff0c;可以把此脚本放在桌面上作为一个小工具&#xff0c;运行即可。 代码(核心部分是chatGPT自…

高压放大器研究方向及其应用领域

高压放大器是一种电子设备&#xff0c;用于将输入信号的电压增大到较高的输出电压。它在许多领域中有广泛的应用&#xff0c;包括通信、医疗、科学研究等。 高压放大器的研究方向主要集中在以下几个方面&#xff1a; 提高功率效率&#xff1a;高压放大器需要能够提供足够的输出…

信号可靠性剖析

问题 基于信号发送的进程间通信方式可靠吗&#xff1f;&#xff1f;&#xff1f; 信号查看(kill -l) 信号的分类 不可靠信号 (传统信号) 信号值在 [1, 31] 之间的所有信号 可靠信号 (实时信号) 信号值在 [SIGRTMIN&#xff0c;SIGRTMAX]&#xff0c;即&#xff1a;[34&…

数据挖掘 分类模型选择

选择的模型有&#xff1a; 决策树、朴素贝叶斯、K近邻、感知机 调用的头文件有&#xff1a; import numpy as np import pandas as pd from matplotlib import pyplot as plt from sklearn.linear_model import Perceptron from sklearn.naive_bayes import GaussianNB from s…

二极管:TVS瞬态抑制二极管

一、什么是TVS二极管 TVS&#xff08;Transient Voltage Suppressors&#xff09;&#xff0c;即瞬态电压抑制器&#xff0c;又称雪崩击穿二极管。 TVS二极管的符号如下图所示 什么是雪崩击穿 雪崩击穿是有必要了解一下的&#xff0c;不然后面还有齐纳击穿&#xff0c;搞不…

PySpark开发环境搭建常见问题及解决

PySpark环境搭建常见问题及解决 1、winutils.exe问题2、SparkURL问题3、set_ugi()问题 本文主要收录PySpark开发环境搭建时常见的一些问题及解决方案&#xff0c;并收集一些相关资源 1、winutils.exe问题 报错摘要&#xff1a; WARN Shell: Did not find winutils.exe: {} ja…

阿里云Arthas使用——在日志没有输出异常情况下,如何进行线上bug定位 stack命令 和 trace命令

前言 Arthas 是一款线上监控诊断产品&#xff0c;通过全局视角实时查看应用 load、内存、gc、线程的状态信息&#xff0c;并能在不修改应用代码的情况下&#xff0c;对业务问题进行诊断&#xff0c;包括查看方法调用的出入参、异常&#xff0c;监测方法执行耗时&#xff0c;类…

算法学习系列(五):N皇后、数独

目录 引言一、N皇后问题代码实现测试 二、数独问题代码实现测试 引言 这个N皇后问题是很典型的一个递归问题&#xff0c;就是还是要掌握&#xff0c;所谓递归其实就是dfs&#xff0c;一层一层深入下去。数独和N皇后的思路是一样的&#xff0c;只不过一些细节不同而已。 一、N…

【恋上数据结构】前缀树 Tire 学习笔记

Tire 需求分析 如何判断一堆不重复的字符串是否以某个前缀开头&#xff1f; 用 Set\Map 存储字符串&#xff08;不重复&#xff09;遍历所有字符串进行判断缺点&#xff1a;时间复杂度 O(n) 有没有更优的数据结构实现前缀搜索&#xff1f; Tire&#xff08;和 Tree 同音&a…

Linux 和 macOS 的主要区别在哪几个方面呢?

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;数据结构&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;网络编程等领域UP&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff0…

Hadoop学习笔记(HDP)-Part.08 部署Ambari集群

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

Unity-Shader - 2DSprite描边效果

实现一个简单的2D精灵图描边效果&#xff0c;效果如下 实现思路&#xff1a; 可以通过判断该像素周围是否有透明度为 0的值&#xff0c;如果有&#xff0c;则说明该像素位于边缘。 所以我们需要打开alpha blend&#xff0c;即&#xff1a; Blend SrcAlpha OneMinusSrcAlpha&am…

腾讯云轻量应用服务器怎么使用宝塔面板?

腾讯云轻量应用服务器宝塔面板怎么用&#xff1f;轻量应用服务器如何安装宝塔面板&#xff1f;在镜像中选择宝塔Linux面板腾讯云专享版&#xff0c;在轻量服务器防火墙中开启8888端口号&#xff0c;然后远程连接到轻量服务器执行宝塔面板账号密码查询命令&#xff0c;最后登录和…