指针详解(2)

news2025/1/4 19:16:39

指针详解(2)

对数组名的理解

在C语言里数组名还表示着数组首元素地址。

int arr[5] = {1, 2, 3, 4, 5};
int* p = &arr[0];
int* p = arr;

以上这两种,对指针p进行赋值的操作均是等价的,都将数组首元素的地址赋给指针p。

不妨,我们可以测试一下

int main()
{
	int arr[5] = {1, 2, 3, 4, 5};
	printf(" &arr[0] = %p\n", &arr[0]);
	printf(" arr     = %p\n", arr);
	return 0;
}

在这里插入图片描述

更具运行结果能够证明,arr 与 &arr[0] 是等价的,都表示着数组首元素的地址


但也有两个例外,

  • sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位字节
  • &数组名,数组名表示整个数组,取出的是整个数组的地址。(整个数组的地址与首元素地址有区别的)

​ 除此之外,数组名表示首元素的地址

int main()
{
	int arr[5] = { 1, 2, 3, 4, 5 };
	printf("sizeof(arr) = %d\n", sizeof(arr));
	return 0;
}

在这里插入图片描述

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

在这里插入图片描述

这里会不会看着有点懵,&arr,与arr地址是相同的。不妨看看这串代码。

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

在这里插入图片描述

根据运行结果不难看出,

  • &arr[0] 和 arr,表示着数组名首元素的地址

  • &arr[0] + 1 和 arr + 1,表示第二的数组元素的地址,地址大小加4

  • &arr,表示整个整个数组元素,打印的地址是首元素的地址

  • &arr + 1,由00AFF934 - 00AFF920得出地址向后偏移了20个字节,意味着&arr + 1跳出了数组元素的空间,指向了一块没有使用的空间

int arr[5] = { 1, 2, 3, 4, 5 };
int* p = arr + 1;
printf("p = %n\n", p);

可以运行这窜代码,将会报错,指针变量p 现在是一个野指针,使用printf函数解引用会报错。

一维数组传参本质

有了上述对数组名的理解,看看一下代码试着猜测运行结果。

void test(int arr[])
{
	printf("sizeof(arr) = %d\n", sizeof(arr));
}
int main()
{
	int arr[5] = { 1, 2, 3, 4, 5 };
	printf("sizeof(arr) = %d\n", sizeof(arr));
	test(arr);//等价test(&arr[0]);
	return 0;
}

运行结果:
在这里插入图片描述

很明显在函数里计算数组元素的大小为4,主函数里为20。

根据代码运行结果发现,一维数组在进行传参时,因为数组名是首元素地址,在本质上传递的实际上是数组首元素的地址。在在理论上参数因该使用指针变量来接收数组元素的指针。

函数里使用sizeof(arr)计算数组大小时实际上计算的是指针变量的大小而不是数组的大小。
在这里插入图片描述

这里将编译器改变为64位,重新运行代码后的结果,在64位下计算指针的大小,为8个字节。


由于传递的是地址,在函数里可以使用指针变量来接收

void test(int* arr)
{
	//printf("arr[2] = %d", arr[2]);
	printf("*(arr + 1)= %d", *(arr + 1);//两者等价
}

这里,通过指针的写法来访问数组元素,*(数组名 + 下标),这种写法与 arr[1]是等价的,数组名表示收元素地址,对地址+ 1或+ 其它数字,地址就会跳转到该数字对应下标的数组元素。

int main()
{
	int arr[5] = { 1, 2, 3, 4, 5 };
	printf("*(arr + 4) = %d\n", *(arr + 4));
	return 0;
}

注意:数组下标最大是4,在使用指针的写法时,*(arr + 5)这样是错误的写法,将会对野指针解引用,程序报错。

二级指针

指针变量用来存放变量地址,那指针变量的地址呢?变量的地址存放在二级指针里

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

在这里插入图片描述

变量地址
a=*pa=**ppa0X00FFA40
pa=*ppa0X00FFA80X00FFA4
ppa0X00FFAC0X00FFA8

对一级指针pa进行解引用 *pa,找到了变量a,a的值为 0,对二级指针ppa进行解引用找到了一级指针pa,pa的值为0X00FFA4,是变量a的地址,在进行解引用就找到了变量a,a的值为0。


案例:对二级指针 ppa解引用一次

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

这里对二级指针进行解引用(*ppa),实际上就是对一级指针进行操作,将b的地址赋给一级指针pa。它们之间的关系变为:

变量地址
b=*pa=**ppa0X00FFA020
pa =*ppa0X00FFA80X00FFA0
ppa0X00FFAC0X00FFA8

对ppa解引用两次就是b的值,打印的结果为20

在这里插入图片描述

指针数组

指针数组是什么?是指针,还是数组?更具之前学习过的,整形数组(int arr[]),字符数组(char arr[]),整形数组使用来存放整形的数组,字符数组是用来存放字符的数组,指针数组使用来存放指针的数组吗?是滴没错!

在这里插入图片描述

指针数组的写法,它可以是整形,也可以是字符类型,int* arr[5]; char* arr[5];

数字5代表着这个指针数组可以存放5个指针变量。指针数组与整形数组字符数组的理解相比并不难,它只是用来存放指针的数组。

初始化:

int a = 10;
int b = 6;
int* parr[2] = {&a, &b};

int* p[5] = { 0 };

使用指针数组,它与常见的整形数组用法区别不大

printf("%d\n", *parr[0]);

由于数组里存放的是指针,parr[0]是一个指针,对指针进行解引用来获取它指向的数据。

使用指针数组模拟二维数组

首先,二维数组在空间上是连续存放的,int arr[3][5];,arr数组里,每行有5个元素,一共有三行,我们说可以近似的将这个三行的二维数组看作三个一维数组的拼接,诶~事实上是可以这样操作的。是以指针数组就可以完成这样的作法。

#include <stdio.h>
int main()
{
	int i, j;
	int arr1[5] = { 0 };
	int arr2[5] = { 0 };
	int arr3[5] = { 0 };
	int* parr[5] = {arr1, arr2, arr3};
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			parr[i][j] = i + j;
		}
	}
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			printf("%d ", parr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

在这里插入图片描述

​ 这里呢,使用指针数组模拟了二维数组的赋值和打印,为什么可以这样 parr[i][j]; ,数组下标引用操作符,本质上可以理解为 *(arr + 1),对数组首元素加有效的数字,就获得数组下标对应元素的地址,然后进行解引用,就获取了地址对应的值,parr[i][j]; 同样是这样理解,第一个下标引用操作符找到这个指针数组的元素,

parr[0][j] 等价 arr1[j] ,在对arr1使用数组下标引用操作符就可以找到 i,j对应的位置,和元素。

​ 同理,也可以使用二级指针模拟二维数组。首先对二级指针开辟空间一块整形指针类型的空间,然后在循环里

对每一个整形指针开辟相同大小的空间,就完成了对二维数组结构建立,之后就可以正常使用下标引用操作符,对二级指针赋值,打印之类的操作。

有效的数字,就获得数组下标对应元素的地址,然后进行解引用,就获取了地址对应的值,parr[i][j]; 同样是这样理解,第一个下标引用操作符找到这个指针数组的元素,

parr[0][j] 等价 arr1[j] ,在对arr1使用数组下标引用操作符就可以找到 i,j对应的位置,和元素。

​ 同理,也可以使用二级指针模拟二维数组。首先对二级指针开辟空间一块整形指针类型的空间,然后在循环里

对每一个整形指针开辟相同大小的空间,就完成了对二维数组结构建立,之后就可以正常使用下标引用操作符,对二级指针赋值,打印之类的操作。

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

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

相关文章

【C++进阶学习】第六弹——set和map——体会用C++来构建二叉搜索树

set和map基础&#xff1a;【C进阶学习】第五弹——二叉搜索树——二叉树进阶及set和map的铺垫-CSDN博客 前言&#xff1a; 在上篇的学习中&#xff0c;我们已经学习了如何使用C语言来实现二叉搜索树&#xff0c;在C中&#xff0c;我们是有现成的封装好的类模板来实现二叉搜索树…

SpringBoot新手快速入门系列教程六:基于MyBatis的一个简单Mysql读写例子

我的教程都是亲自测试可行才发布的&#xff0c;如果有任何问题欢迎留言或者来群里我每天都会解答。 MyBatis和JPA是两种不同的Java持久层框架&#xff0c;各有其优缺点。以下是它们的比较&#xff1a; MyBatis 优点 灵活性高&#xff1a;MyBatis允许手动编写SQL查询&#xf…

AWDAWFAAFAWAWFAWF

创建两张表&#xff1a;部门&#xff08;dept&#xff09;和员工&#xff08;emp&#xff09; 创建视图v_emp_dept_id_1&#xff0c;查询销售部门的员工姓名和家庭住址 创建视图v_emp_dept&#xff0c;查询销售部门员工姓名和家庭住址及部门名称 创建视图v_dept_emp_count(dept…

Ubuntu: gitee免密

安装git sudo apt-get install git下载 git clone XXX SSH keys 第一步&#xff1a;检查本地是否有 SSH Key存在 ls -al ~/.ssh第二步&#xff1a;配置你注册的邮箱 ssh-keygen -t rsa -C "your_emailexample.com"输入命令后一直回车 第三步&#xff1a;获取公钥…

乐观锁原理

乐观锁是一种并发控制的方法&#xff0c;主要用于多线程环境下&#xff0c;用于保证数据的一致性。其核心思想是&#xff1a;"在多个事务中乐观地读取数据&#xff0c;在提交时再验证是否有冲突&#xff0c;如果没有&#xff0c;则提交&#xff1b;如果有&#xff0c;则回…

使用 Apache DolphinScheduler 构建和部署大数据平台,将任务提交至 AWS 的实践经验

作者介绍 李庆旺 - 软件开发工程师&#xff0c;思科 引言 大家好&#xff0c;我是李庆旺&#xff0c;来自思科的软件开发工程师。我们的团队已经使用Apache DolphinScheduler搭建我们自己的大数据调度平台近三年时间。从最初的2.0.3版本开始至今&#xff0c;我们与社区一同成…

基于FPGA的数字信号处理(15)--定点数的舍入模式(6)向0取整fix

前言 在之前的文章介绍了定点数为什么需要舍入和几种常见的舍入模式。今天我们再来看看另外一种舍入模式&#xff1a;向上取整fix。 10进制数的fix fix&#xff1a;也叫 向0取整。它的舍入方式是数据往0的方向&#xff0c;舍入到最近的整数&#xff0c;比如1.75 fix到2&#xf…

【操作系统】进程管理——管程(个人笔记)

学习日期&#xff1a;2024.7.12 内容摘要&#xff1a;管程的定义和基本特征 管程 管程存在的意义&#xff1a;在上一章节中&#xff0c;我们学习了利用信号量机制解决进程同步互斥问题的方法&#xff0c;信号量机制编写程序较为复杂困难&#xff0c;易出错。为了让程序员写程…

MySQL查询语句(DQL)

文章目录 查询语句&#xff08;DQL)简单查询查一个字段查多个字段查所有字段查询字段可以进行数学运算查询时字段可起别名 条件查询and (&&)or (||)between...and...is null 和 is not nullin 和 not inlike (模糊查询) 查询语句&#xff08;DQL) 简单查询 \c可以清空…

JavaScript中的拷贝技术探秘:浅拷贝与深拷贝的奥秘

最新技术资源&#xff08;建议收藏&#xff09; https://www.grapecity.com.cn/resources/ 前言 JavaScript中的浅拷贝和深拷贝是非常重要的概念&#xff0c;它们在处理对象和数组时具有不同的作用。在编程中&#xff0c;经常需要复制数据以便进行各种操作&#xff0c;但必须注…

【python】Python报错分析:深入探索`IndexError`及其解决办法

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

GlobalSign证书介绍以及申请流程

在当今高度互联的世界中&#xff0c;网络安全与数据保护的重要性日益凸显&#xff0c;而数字证书作为保障网络通信安全的关键技术&#xff0c;已成为构建数字信任的基石。GlobalSign&#xff0c;作为全球数字证书行业的先驱和领导者&#xff0c;自成立以来便致力于为全球企业和…

unity 手动制作天空盒及使用

提示&#xff1a;文章有错误的地方&#xff0c;还望诸位大神不吝指教&#xff01; 文章目录 前言一、使用前后左右上下六张图1.准备6张机密结合的图片2.创建Material材质球3.使用天空盒 二、使用HDR贴图制作1.准备HDR贴图2.导入unity 修改Texture Sourpe 属性3.创建材质球4.使用…

Jenkins 离线升级

1. 环境说明 环境 A: jenkins 版本&#xff1a;2.253使用 systemctl 管理的 jenkins 服务 环境 B&#xff1a; 可以上网的机器&#xff0c;装有 docker-compose docker 和 docker-compose 安装&#xff0c;这里都略了。 2. 安装旧版本 2.1 环境 A jenkins 目录打包文件 …

ARM 虚拟机FVP环境搭建

ARM Fixed Virtual Platforms (FVPs) 是由 ARM 提供的一系列虚拟化硬件模拟器&#xff0c;用于在物理硬件可用之前开发和测试软件。FVP 模型非常适用于软件开发、验证和性能分析&#xff0c;涵盖了从裸机到操作系统和复杂 SoC 系统的各种应用。 这里以Cortex-M55为例&#xff0…

80. UE5 RPG 实现UI显示技能冷却进度功能

在上一篇文章里&#xff0c;我们实现了通过GE给技能增加资源消耗和技能冷却功能。UI也能够显示角色能够使用的技能的UI&#xff0c;现在还有一个问题&#xff0c;我们希望在技能释放进去冷却时&#xff0c;技能变成灰色&#xff0c;并在技能冷却完成&#xff0c;技能可以再次使…

【算法】代码随想录之数组

文章目录 前言 一、二分查找法&#xff08;LeetCode--704&#xff09; 二、移除元素&#xff08;LeetCode--27&#xff09; 三、有序数组的平方&#xff08;LeetCode--977&#xff09; 四、长度最小的子数组&#xff08;LeetCode--209&#xff09; 五、螺旋矩阵II&#x…

LLM:tokenizer分词器概念

在做nlp时&#xff0c;首先要对文本进行分词&#xff0c;也就是给定一个句子&#xff0c;将其归到词表中的一系列token上&#xff0c;token有对应的数字&#xff08;token_id&#xff09;。 上图是bert的分词器的json内容&#xff0c;可以看到词表是一个字典&#xff0c;key为t…

电脑显示MSVCR110.dll丢失怎么办,总结5种靠谱的解决方法

在使用电脑过程中&#xff0c;部分用户可能会遇到MSVCR110.dll文件丢失的问题&#xff0c;具体表现为弹出提示窗口&#xff0c;指出缺失该文件&#xff0c;导致部分程序无法正常启动。小编将为您介绍多种解决该问题的指南。 一、找不到MSVCR110.dll是什么情况 MSVCR110.dll是M…

2.线性回归

简化的房价模型 假设1&#xff1a;影响房价的关键因素时卧室个数&#xff0c;卫生间和居住面积&#xff0c;记为 x 1 , x 2 , x 3 x_1,x_2,x_3 x1​,x2​,x3​ 假设2&#xff1a;成交价时关键因素的加权和&#xff1a; y w 1 x 1 w 2 x 2 w 3 x 3 b y w_1x_1w_2x_2w_3x…