指针详解(一)——指针概念、指针类型、野指针、指针运算、指针关系运算、二级指针

目录

指针概念

指针的定义

指针的大小

指针类型

指针有哪些类型

指针类型有什么意义

野指针

野指针的含义:

造成野指针的原因:

 如何规避野指针

指针运算

1.指针+-整数

2.指针- 指针

指针的关系运算

二级指针


指针概念

指针的定义

在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的内存单元,可以说地址指向该内存单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。

理解指针的两个要点:

  • 指针是内存中一个最小单元的编号,也就是地址
  • 平时口语中说的指针,通常指的是指针变量,是用来存放地址的变量

这是官方对指针的定义,其实我们可以理解为:在内存中,内存被细分为一个个大小为一个字节的内存单元,每一个内存单元都有自己对应的地址。

形象地比喻,我们把一个个内存单元看成一个酒店房间,我们的指针就是我们手里的门禁卡上面写着所指向的房间序列也就是地址,通过指针我们就能对应地找到所开辟的内存空间,并调用其中的数据,即用指针指向内存单元

指针变量就是用来存放地址的变量(放在指针中的值都被当成地址来处理)

#include<stdio.h>
int main()
{
    int a=1;
    int *p=NULL;
    p=&a;
    return 0;
}

这里p就是指针变量,它存放着a的地址 

指针的大小

32位机器是指处理器一次能处理的最大位数是32位,通常指CPU里面的通用寄存器的数据宽度是32个比特位。而64位机器表示一次能处理的最大数据位数是64位。
32位机器最大寻址地址空间是2^32次方个内存单元(4G),注意1G=2^30,而每个内存单元大小都是一个字节,所以32位机器最大寻址空间是4GB。
而64位机器最大寻址空间是4GB^32,这个数字相当庞大,通常只能寻址到128GB

32位机器有32根地址线,每根地址线都能发出0或1,所以由32位机器发出的地址信号总共有2^32种排列方式:

所以                                                       

在32位的机器上每个地址是32位,而8个bit位为一个字节,所以在32位机器上指针大小为4个字节

同理在64位机器上,指针大小为8个字节

指针类型

指针有哪些类型

因为指针是指向具有类型的变量的地址,所以指针肯定也有不同的类型 

指针的定义方式是type+ *
char * 类型的指针存放的是char类型的变量地址;
int * 类型的指针存放的是int类型的变量地址;
float * 类型的指针存放的是float类型的变量地址等。

指针类型有什么意义

指针类型决定指针在被解引用的时候访问的权限

例如:整型指针解引用访问4个字节(如图)

          字符指针解引用访问1个字节等等

指针类型也决定了指针向前或向后走一步走多大的距离

#include<stdio.h>
int main()
{
    int a=10;
    int *pa=&a;
    char*pd=&a;

    printf("%p\n",pa);
    printf{"%p\n",pd);


    printf("%p\n",pa+1);
    printf{"%p\n",pd+1);
    
    return 0;
}

    

(这里的pd的指针类型与a的数据类型不统一,这里只是为了方便展示地址的变化,在平时的编程中一定要注意类型要统一!)

得到的结果是:

用图表示如下:

野指针

野指针的含义:

指针指向的位置是不可知的(随机的,不正确的,没有明确限制的),就如同上述所说,我们使用自己的门牌卡(指针)去访问自己订的房间(内存单元),只有进入自己所订的房间才是合法的,如果闯入其他的房间就是非法访问,是违法的;而当我们退房时(内存空间释放),我们手中的门牌卡(指针)也是没有权限再去访问我们之前的房间(内存单元);

造成野指针的原因:

  • 指针未初始化
  • 指针越界访问
  • 指针指向的空间释放

 如何规避野指针

  • 指针初始化
  • 小心指针越界
  • 指针指向空间释放即时置NULL
  • 避免返回局部变量的地址
  • 指针使用之前检查有效性

指针运算

1.指针+-整数
#include<stdio.h>
int main()
{
	int arr[5] = { 0 };
	int* p = arr;
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		*(p + i) = i;
	}
	return 0;
}
2.指针- 指针
int my_strlen(char* p)
{
	char* pc = p;
	while (*p != '\0')
		p++;
	return p - pc;
}

指针-指针的绝对值是是两个指针之间的元素个数, strlen函数的模拟实现就可以运用指针-指针的代码实现(两个指针必须指向同一块空间)

指针的关系运算

指针的关系运算指的是指针之间大小的比较

例如我们想将一个数组中的元素全部置为0,有两种方法:

1.从前往后置0

#include<stdio.h>
int main()
{
	int arr[5] = { 1, 2, 3, 4, 5 };
	int* p = &arr[0];
	for (p = &arr[0]; p <= &arr[4]; p++)
	{
		*p = 0;
	}
	return 0;
}

2.从后往前置0

#include<stdio.h>
int main()
{
	int arr[5] = { 1, 2, 3, 4, 5 };
	int* p = &arr[4];
	for (p = &arr[4]; p >= &arr[0]; p--)
	{
		*p = 0;
	}
	return 0;
}

规范的使用方法是第一种,从前往后置0;

因为指针关系运算的标准规定:

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

二级指针

其实,存放普通变量的地址的指针叫一级指针,存放一级指针变量的地址的指针叫二级指针,存放二级指针变量地址的指针叫三级指针,以此类推

二级指针是指向一级指针变量地址的指针

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

    printf("%p\n",&a);    
    printf("%p\n",p);
    printf("%p\n",pp);

    return 0;
}

得到的结果: 

可知:对二级指针pp第一次解引用时即*pp,得到的值就是一级指针变量p的值,即为a的地址,再解引用即**pp,就等于a的值,相当于对一级指针p解引用;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LLhaibao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值