0
点赞
收藏
分享

微信扫一扫

指针详解1:指针的概念以及野指针

拾光的Shelly 2022-01-05 阅读 114

在说指针之前,肯定要去了解一个问题:指针是什么?

        指针是一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值;

由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元,地址形象化起名指针

        通过地址可以找到内存单元

        指针是个变量,存放内存单元的地址(编号)

那么我们来看一段程序:

#include<stdio.h>
int main()
{
	int a = 10;
	int* p = &a;  //指针变量,存储地址,存放在指针中的值当成地址处理
	//对变量a进行取地址操作,将地址存到p中,p就是一个指针变量
	printf("a的地址是%p", p);
	return 0;
}

这段程序注释已经给出,int*是一种变量类型,而p的类型就是int*,所以p可以存储地址,

而*p(解引用)一般用来存值

那么:

一个小单元多大?一个字节,如何编址?

对于32位的机器,假设有32根地址线,每个地址线在寻址产生一个正电或负电

地址就是

00000000 00000000 00000000 00000000   ~~~

11111111 11111111 11111111 11111111 共2的32次方个地址

每个地址标识一个字节,

2^32Byte == 2^32/1024KB == 2^32/1024/1024MB ==2^32/1024/1024/1024GB == 4GB

这也就是地址的工作原理了

在32位的机器上,地址由0或者1组合32位成序列,需要用四个字节的空间来存储,所以一个指针变量的大小就是4个字节

 在64位机器上,一个指针变量就应该是8个字节大小

那我们不禁需要思考一个问题:

指针大小均为4,那么指针类型究竟有什么实际意义?

/*int* pa = &a;

*pa = 0; //四个字节的内容均改为00

char* pc = &a;

*pc = 0;  //只动了一个字节的内容

int*p 能够访问4个字节

char*p 能够访问1个字节

double*p 能够访问8个字节*/

指针类型决定了指针进行解引用操作时,能够访问的空间大小

指针可以+-整数吗?--可以

因为指针类型决定了指针一步有多远(指针的步长),加减整数实际上就是走了几步

int*p  p+1 --> 4个字节

char*p p+1 --> 1个字节

double*p p+1 --> 8个字节

=========================================================================

同理,应用到数组中,也可以使用指针的步长变化进行数组的遍历:

#include<stdio.h>
{
    int arr[10] = { 0 };
	//char* p = arr;//数组名,首元素地址
	int* p = arr;
	int i = 0;
	for (i = 0; i <= 9; i++)
		*(p + i) = 1;
	for (i = 0; i <= 9; i++)
		printf("%d  ", arr[i]);
	return 0;
}

当然,也可以这样打印数组:

void print_arr()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	char* a = arr;
	for (int i = 0; i < sz; i++) {
		printf("%d  ", *p);
		p += 1;//p++ 指针加整数:跨步长(int,char,double..等)操作
	}//1  2  3  4  5  6  7  8  9  10
	printf("\n");
	for (int i = 0; i < sz; i++) {
		printf("%d  ", *a);
		a += 2;
	}//1  0  2  0  3  0  4  0  5  0
	printf("\n");
	a = arr;
	for (int i = 0; i < sz; i++) {
		printf("%d  ", *a);
		a += 4;  //注意,如果此时不把指针复原,指针会越界
	}//1  2  3  4  5  6  7  8  9  10
	printf("\n");
	//思考:利用指针倒序打印数组?
	p -= 1;//因为此前已经移动了指针的地址到p+10,所以可以减一成为p+9
	for (int i = 0; i < sz; i++) {
		printf("%d  ", *p);
		p -= 1;
	}//10  9  8  7  6  5  4  3  2  1
}

同时,一定注意指针越界的问题,如果直接让指针变量自增,可能会出现越界的问题。

二维数组同样可以进行类似操作,我们一会儿再讲这个问题。

=========================================================================

指针既然可以移动,并且在字符串或者数组上都可以,那我们是不是可以使用指针实现求串(或者数组)的长度?--当然可以,这里给出字符串类型的求长,数组的也类似。

int my_strlen(char* str)
{
	//strlen-->求字符串长度
	char* start = str;
	char* end = str;
	while (*end != '\0')
	{
		end++;
	}
	return end - start;
}

在使用指针指向数组的时候,要注意越界的问题,同时也要注意:允许某个指针与指向数组最后一个元素后的内存位置的指针比较,不允许与指向第一个元素前的内存位置的指针比较

=========================================================================

那么,我们可以给任意变量赋初始值,指针类型也不例外:

不知道指针初始化该指向谁,就使用NULL

NULL -- 用来给指针初始化的。

检查有效性:

/*pa = NULL;

if(pa != NULL)

{......}

else{......}*/

那么在详解一里,我们最后再看一下野指针的问题,二级指针将放在详解二里介绍:

野指针,野指针是什么?

野指针:指针指向的位置不可知(随机的,不正确的,没有明确限制的)

野指针的成因:

int x;//局部变量不初始化,默认随机值

int* p;//局部指针变量不初始化,野指针

指针越界也会野指针

//或者指向一个被释放的值(函数)

如何避免?

指针初始化,变量被释放就置NULL,小心指针越界,使用之前检查有效性

那么指针详解一就到这里了,喜欢的小伙伴可以点个赞支持一下。

举报

相关推荐

0 条评论