指针1

118 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情


1.指针

1. 指针是什么

我们口头说的指针就是地址, 指针变量是变量,是用来储存地址的。

2. 指针和指针类型

#include <stdio.h>
int main()
{
	int a = 0;
	int* p = &a;
	*p = 20;
	printf("%d\n",a);
	printf("%d\n",*p);
	return 0;
}

对于上面的代码 这里的==p==是指针变量——是用来存放地址的变量; 可以这样理解从*可以看出p是个指针变量,p指向的内容是int类型的。 *p = 20,此处的 * 是解引用操作符。 &为取地址操作符 指针的类型是根据原来值的类型来确定用什么类型的指针。如:char类型,那就用char* 。 去掉指针变量名剩下的就是指针的类型

关于指针类型的声明有人可能会问用不同的类型声明可以吗?当然可以,但是会出现一些问题。 不同的指针类型决定了指针解引用所移动的步长 如:char类型的,那么它+1就指向下一个字节(向后走一步) int 类型的,那么它+1就指向到第4个字节处。(向后走4步) 指针的类型代表它所能访问几个字节大小的空间 看下面这个代码

int main()
{
	int a = 0x11223344;
	char* p = (char*)&a;
	*p=0;
	printf("%x", a);
	return 0;
}

此处的&a应该是int*类型的,但强转成char*类型的指针之后,对p进行解引用赋值成0只能改变一个字节,所以输出的结果是11223300。 看计算机输出的结果 在这里插入图片描述

指针的大小由电脑的平台所决定的而不是由指针类型决定的。 如果平台上是32位的,那就是4个字节的大小;64位的平台就是8个字节的大小。 看下面这个代码可以看出来:

#include <stdio.h>
int main()
{
	printf("%d\n", sizeof(int*));
	printf("%d\n", sizeof(char*));
	printf("%d\n", sizeof(long*));
	printf("%d\n", sizeof(float*));
	return 0;
}

在这里插入图片描述

在我的32位平台上上面的输出结果都是4。

3. 野指针

野指针就是指针访问了位置不可知的地方,造成非法访问

🥇1. 指针没有初始化

比如这样:

	int* i;
	这样写是不对的,指针i指向的空间不知道
	可以这样写:
	int* i=NULL;

🥈2. 指针越界访问

看下面这个代码:

	int arr[5]={1,2,3,4,5};
	int* p=arr;
	int i=0;
	for(i=0;i<=5;i++)
	{
		*(p++)=i;
	}

该数组里面有5个元素,当i为5时,p访问的空间超过了数组的范围 造成越界访问,这时p就是野指针.

🥉3. 指针指向的空间被释放

int* f(int* a,int* b)
{
	int c = 0;
	c = *a + *b;
	return &c;

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

在调用函数的过程中开辟的空间,出了这个了函数,则开辟的空间返还给操作系统,导致p指针接受的地址被释放,次数p为野指针。 虽然在vs 上面依然可以输出,但是确实是错误的。需要注意。

还有这种,和上面的差不多:

int main()
{
	int* p = (int*)malloc(4 * sizeof(int));
	int i = 0;
	if (p != NULL)
	{
		for (i = 0; i < 4; i++)
		{
			*(p + i) = i;
		}
	}
	free(p);
	for (i = 0; i < 4; i++)
	{
		printf("%d ", *(p + i));
	}
	return 0;
}

在p指向的空间被释放后,它所指向的空间被返还给操作系统 再次对它解引用进行访问就造成非法访问。 通常在释放空间后加上p=NULL

4. 指针运算

  • 🚗 ==指针加减整数==

指针加一个整数表示该指针向后走几个该指针所指类型字节的个数。

比如:

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8 };
	int p=*(arr + 4);
	return 0;
}

p就是5,因为数组的每个元素都是int类型的,所以arr+4表示arr向后走4个int类型的字节数,即访问数组第5个元素。

指针减整数也是同理,注意不要越界访问

  • 🚓==指针相减==

指针相减得到的是两个指针之间的元素个数,不要认为是地址相减的结果,不要问为什么,这是这么规定的。

看下面的代码帮助你理解:

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

输出的结果是4哦😁 在这里插入图片描述

  • 🚕==指针做比较==

指针也是有大小的,就比如有高地址与低地址这么一说

c语言标准规定

允许指针与指针指向数组的最后一个元素后面的那个地址进行比较,不允许和指针指向数组第一个元素前面的那个地址进行比较。 再次说明不要问为什么,规定就是规定

例子:

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8 };
	int* p;
	for (p=arr;p<=&arr[7];p++)
	{
		;
	}
	上面这个可以,下面这个不可以,原因上面说的非常清楚
	for (p = &arr[7]; p >= arr; p--)
	{
		;
	}
	return 0;
}

5. 二级指针

指针的地址怎么储存呢?——用二级指针变量进行储存

	int i=0;
	int* p=&i;
	int** p1=&p;

指针的指针就是二级指针,用于储存一级指针的地址。要改变i的值p1要解引用2次才可以改变