野指针的成因以及指针运算

目录

指针和指针类型

指针 + - 整数 

指针de解引用

 指针易错题

野指针 

野指针成因

1.指针未初始化

2.指针越界访问

3.指针指向的空间释放

指针运算

指针 + - 整数

指针 - 指针

指针运算关系



指针和指针类型

一个变量有它的类型 int short double float ……那么一个指针有没有属于它的类型呢?

当然有啦,但是不同的指针类型的指针大小都是4/8个字节大小。

指针 + - 整数 

指针的加减同样与指针的类型有关。

c8e1e78398794037880f18a001f3b056.png

 将同一个地址放在不同类型的指针变量中,+1的结果都不一样的。int类型的指针+1会加四个字节而char类型的指针+1仅仅加一个字节。


指针de解引用

指针的类型决定了在解引用的时候可以访问几个字节


d71cd8236fcb4eba81e7d6132c8bdf51.png

173ff077087f46df89ea54ab567dfc54.png

502df968c294492d988bfcaddc47fe9e.png

 这里图3的指针是char类型,在解引用时访问的是一个字节;而图2是int类型,在解引用时访问的是四个字节。

 指针易错题

代码1:
#include<stdio.h>
int main()
{
	int arr[10] = {0};
	int* p = &arr;//int 类型指针
	for (int j = 0; j < 10; j++)
	{
		*p = j;
		p++;	//指针+1
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d", arr[i]);

	}
	return 0;
}
代码2:
#include<stdio.h>
int main()
{
	int arr[10] = {0};
	char* p = &arr;//char 类型指针
	for (int j = 0; j < 10; j++)
	{
		*p = j;
		p+=4;	//指针+4
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d", arr[i]);

	}
	return 0;
}

各位觉得这两份代码表示的含义是不是一模一样的呢?

:准确来说,并不是,虽然两份代码的执行结果是一样的,但是表示的意义却相差万里。

代码1中的*p访问的是4个字节的空间,但是代码而访问的确实一个字节的空间,假如说代码1与代码2的数组初始化时的另外三个字节的空间存放的不是0,那么两代码执行结果也就不一样了。


野指针 

概念:野指针就是指针指向的位置未知,不确定……造成的。

野指针成因

1.指针未初始化

0640dc2086a2481f98725e8b0cf6d723.png

 这里的指针变量p就未初始化,故存放一个随机值,而*p访问的空间不一定是自由的,是随机的·。

2.指针越界访问

a19b7c96d9af4bbe80557403c4c9d6dc.png

3.指针指向的空间释放

723a58e193ca4758aea10e9b749c80d7.png

 这里的a是局部变量,出了作用域就销毁了,因此a的地址在出了作用域之后也就被释放了,所以想再次通过 *p 访问 a 就不可行了。


指针运算

指针 + - 整数

前文中也提到了指针加减整数的运算,但这里还得补充一下,来看着段代码,是什么意思 :

#define N_VALUES 5//定义标识符常量
#include<stdio.h>
int main()
{
	int arr[N_VALUES];
	int* pa;
	for (pa = &arr[0]; pa < &arr[N_VALUES];)
	{
		*pa++ = 0;
	}

	return 0;
}

 提示:++操作符的优先级大于*操作符,但是这是后置++,所以应该是先解引用后++

故可等价于:*p=0;  p++;

这里的++和--都是赋值操作;操作对象是指针,可不能是数组名(首元素地址)或地址哈。


指针 - 指针

我们先=猜测一下指针 - 指针是什么类型的数吧,是常量,指针,还是其它呢?

前面了解到指针+整数的操作结果是指针,那么我们就可以理解:指针-指针的操作结果就是整数

 那么我们可以理解成 &arr[0]+5=&arr[5] 嘛 

所以说:指针—指针得到的是指针与指针之间的元素个数(您自己也可以用int类型试试看) 


指针运算关系

:码1
#define N_VALUES 5
#include<stdio.h>
int main()
{
	int arr[N_VALUES];
	int* pa;
	for (pa = &arr[N_VALUES]; pa > &arr[0];)
	{
		*--pa = 0;
	}

	return 0;
}
:码2
#define N_VALUES 5
#include<stdio.h>
int main()
{
	int arr[N_VALUES];
	int* pa;
	for (pa = &arr[N_VALUES - 1]; pa >= &arr[0]; pa--)
	{
		pa = 0;
	}

	return 0;
}

代码1与代码2有什么区别呢?

:实际上两代码所表示的意义都是将数组赋值成0.而代码2更好理解,但是代码2在一部分编译器上是不能够执行的,代码2执行的最后一次还发生了指针 pa-- 从而使pa指向的地址就类似于arr[-1],虽然代码1也有这种情况,最后只想arr[5]。

标准规定:允许指向元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个第一个元素之前的那个内存位置的指针进行比较。

猜你喜欢

转载自blog.csdn.net/C_Rio/article/details/128956662