一篇文章教你手撕指针

1.什么是指针?为什么需要指针。

对于这个问题,我们需要思考我们曾经学过的基本程序,它们是如何编译和存储的。指针就是一个地址,任何指针都一样,不存在大小之分。只不过在X86和X64环境下所占字节大小不一样。

那它有什么用呢?举个最基本的例子:"hello world"这个程序,如果你想要从键盘中输入,是怎么做到的呢?

首先我们仔细研究一下  scanf() 这个函数

首先,scanf函数的返回值是int类型,是为了表示成功读取并匹配到的输入项的个数。具体来说,返回值表示成功匹配到的输入项的个数,如果没有匹配到任何输入项,则返回0。如果发生错误或遇到文件结束符,则返回EOF(-1)。这样设计的目的是为了方便判断输入是否成功,并根据返回值进行相应的处理。

其次,参数部分由格式指示符和地址组成。变量列表:变量列表是一系列用于接收输入值的变量。变量列表中的变量必须与格式控制字符串中的格式指示符一一对应,用于存储对应格式的输入值。变量列表中的变量可以是基本数据类型(如int、float、char等),也可以是指针类型。

所以我们时常会在变量前加上一个'&'以表示拿到地址,从而放入或修改数据。如下:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int m;//未初始化
	int b = 521;//已初始化
	scanf("%d %d", &m, &b);
	printf("%d %d", m, b);
	return 0;
}

既能初始化,又能赋值,所以有了地址,无疑增加我们操作数据的能力。

2.指针与数组之间的联系

指针通常使用‘*’表示,和其他数据一样,它是一种数据类型,有int*,char*等等,一颗星,为一级指针,如果给指针加上‘*’表示解引用,类似于数组通过下标访问。举个例子:

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };//创建数组
	for (int i=0;i<10;i++)
	{
		printf("%d ", arr[i]);//通过下标访问
	}
	printf("\n");
	int* p = (int*)malloc(sizeof(int)*10);
	for (int i = 0; i < 10; i++)
	{
		*(p + i) = i;//赋值
		printf("%d ", *(p+i));//通过指针访问
	}
	free(p);
	p = NULL;
	return 0;
}

显然,第一种是大家熟悉的数组创建方式,通过数组下标进行访问。第二种则是利用动态内存开辟空间,分配十个字节,并通过指针解引用,将值写入地址和打印出来。看看运行效果:

效果一样,底层逻辑是一样的。那么二维数组和二级指针效果是一样的。

3.二级指针是什么?

二级指针是指指向指针的指针。它是C语言中的一种特殊数据类型,用于存储指向指针的地址。

在C语言中,指针是一个变量,存储了一个内存地址。而二级指针则是指向指针的指针,它存储的是一个指针变量的地址。

二级指针的声明和使用方式如下:

int main()
{
	int** pp; // 声明一个二级指针
	int* p; // 声明一个指针
	int num = 10; // 声明一个整数变量

	p = &num; // 将指针p指向变量num的地址
	pp = &p; // 将二级指针pp指向指针p的地址

	printf("%d\n", **pp); // 输出变量num的值,使用二级指针需要使用两次解引用操作

     return 0;
}

运行结果:

二级指针常用于需要修改指针变量本身的情况,例如在函数中传递指针的地址,以便在函数内部修改指针的指向。它也可以用于多级指针的情况,例如指向指向指针的指针(三级指针)等。

如果在二级指针内存储一级指针,则可以模拟二维数组

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int** p = (int**)malloc(sizeof(int) * 4);
	for (int i = 0; i < 4; i++)
	{
		 *(p+i) = (int*)malloc(sizeof(int) * 5);
	}
	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			scanf("%d",&p[i][j]);//数组下标输入
		}
		
	}
	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d ", p[i][j]);//数组下标访问
		}
		printf("\n");

	}
	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d ", *(*(p + i) + j));//二级指针解引用访问
		}
		printf("\n");
	}
	free(p);
	p = NULL;
	return 0;
}

两种方式运行结果一样:

4.野指针是什么和如何防范

野指针是指指向无效或未知内存地址的指针。它是一个没有被正确初始化或者指向已经释放的内存的指针。

野指针可能会导致程序运行时的不可预测行为,包括崩溃、数据损坏和安全漏洞等。因此,在使用指针之前,应该始终确保指针被正确初始化或者指向有效的内存地址。

常见产生野指针的情况包括:

  1. 指针未被初始化:在声明指针变量后,没有为其分配有效的内存地址或者将其初始化为NULL。
  2. 指针指向已释放的内存:在释放内存后,没有将指针置为NULL或者重新分配有效的内存地址。
  3. 指针超出作用域:在函数内部定义的指针,在函数结束后可能会超出作用域,成为野指针。
  4. 指针操作错误:对指针进行错误的操作,如解引用空指针、指针运算超出边界等。

为了避免野指针的问题,应该养成良好的指针使用习惯:

  1. 始终为指针变量分配有效的内存地址或者将其初始化为NULL。
  2. 在释放内存后,将指针置为NULL。
  3. 避免指针超出作用域,确保指针在使用期间有效。
  4. 在使用指针之前,进行有效性检查,确保指针指向有效的内存地址。
  5. 避免对空指针进行解引用或者指针运算。

通过遵循这些指针使用原则,可以减少野指针的出现,提高程序的稳定性和安全性。

所以规范使用指针可为你的程序保驾护航。感谢收看,记得三联,摸摸哒!!!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

强sir的世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值