.指针详解
之前我说过一篇关于指针在C语言中的基本使用,这次我再来细讲一下指针的其他内容。
目录
一.指针详解
1.指针定义
2.指针类型
3.野指针
4.如何规避野指针?
1.指针定义
指针理解的2个要点:
1. 指针是内存中一个最小单元的编号,也就是地址。
2. 平时我们所说的指针,通常指的是指针变量,是用来存放内存地址的变量。
int main(){
int a=10;
int* pa=&a; //取出a的地址关联给指针变量
*pa=20; //解引用操作,间接改变变量的值
printf("%d\n",a);//20
return 0;
}
*pa-->0x0012FF40,指针指向的就是变量a的起始地址。
内存会被划分成一个个小小的存储单元,每个内存单元的大小都是固定为1字节(byte)大小。经过大量的计算和权衡,一个存储单元对应一个地址,对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电 平(低电压)就是(1或者0); 那么32根地址线产生的地址就会是:
00000000000000000000000000000000(32bit位全0)
................................................................ 到
1111111111111111111111111111111111111(32bit全1)
共有2^32次方个地址,换算成大单位的话,一块内存大概有4GB的大小。而对于64位系统,则共有2^64次方个地址,约8GB内存。
总结: 指针是用来存放地址的,地址是唯一标示一块地址空间的。
任何指针的大小在32位平台是4个字节,在64位平台是8个字节 。
2.指针类型
C语言中,变量与数组有整数类型,浮点类型,字符类型等,指针也是一样的。
char* 类型的指针是为了存放 char 类型变量的地址。
short* 类型的指针是为了存放 short 类型变量的地址。
int* 类型的指针是为了存放 int 类型变量的地址。
.....
刚才讲到了 任何指针的大小都为4字节(32位中),指针不会因为类型的不同而改变其字节大小,那么指针类型到底有怎样的意义?
a.指针类型意义1:指针变量的解引用
# include<stdio.h>
int main() {
int a = 0x11223344;//地址都是用十六进制表示(0x为16进制表示形式)
int* p = &a;
*p = 0;
printf("%p\n", a);
return 0;
}
在上面的代码中,我将a的地址设置为了0x11223344,使用指针变量关联了a的地址,通过解引用的操作,令指针p将a的值间接化为0,通过调试,可以发现下图中a的地址改为了0x00000000。
十六进制地址中,每两位代表一个字节,所以地址共有4字节大小,而int类型的指针解引用后便可以访问到四字节的地址数,从而将变量a的地址全部换为0。
而char型指针在关联整型变量地址的过程中,指针解引用为0, 也只是改变了变量a地址的一个字节,其他三个字节不变。
我讲解的这两个例子是为了展示指针的访问权限作用:
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。
比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。
b.指针类型意义2.指针的加减操作
int main(){
int n = 10;
char* pn = (char*)&n;
int* pm = &n;
printf("%p\n", &n);
printf("%p\n", pn);
printf("%p\n", pn + 1);
printf("-----\n");
printf("%p\n", pm);
printf("%p\n", pm + 1);
return 0;
}
上图代码中, 创建了两种类型的指针变量去接收同一个变量的地址,通过对两种指针变量+1,产生的结果也是不同。如下图
总结:指针的类型决定了指针向前或者向后走一步有多大(距离)。
以上两种方式展现出来的就是指针类型的真正意义所在!
3.野指针
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)。
野指针用来做比喻的话,其实可以看作一只脾气暴躁的狗,无人管教驯服所以很危险,若不靠近则相安无事,若进行接触或者挑逗它,它就会咬伤我们。
而在C语言中,指针也好比是这样,若不加以初始化给其赋值,它就会产生错误的程序乱码。
int main()
{
int* p;
*p = 10;//非法访问内存了,这里的p就是野指针
return 0;
}
如图代码中指针p没有初始化,就意味着没有明确的指向。一个局部变量不初始化的化,放的是随机值(默认):0xcccccccc
例如在指针作数组遍历访问时,也会遇到野指针的情况
#include <stdio.h>
int main()
{
int arr[10] = {0};
int *p = arr;
int i = 0;
for(i=0; i<=11; i++)
{
*(p++) = i;
}
return 0;
}
如图,数组大小为10,但循环却经历了11次,那么第十一次的循环中 ,当指针指向的范围超出数组arr的范围时,p就是野指针。
注意小贴士:数组允许越界,但不允许使用
例2.指针指向的空间已释放。
int* test()
{
int a = 10;
return &a;
}
int main()
{
int*p = test();
*p = 20;
return 0;
}
这段代码的意思是: 从主函数开始后,通过调用test函数,将a的地址传给指针p,将p解引用后修改a的值。
但我们知道函数中的局部变量一出函数就会被销毁,所以一调用完函数指针P指向的那块空间就已经没了,指针虽然还保留着那块空间的地址,但已经不属于它了,要是继续访问就是非法的,从而指针P就成了野指针。
4.如何规避野指针?
1.创建指针的同时就顺带初始化操作
int a=10;
int*p=&a;
若不知道将指针*p指向谁,就先设成空指针
int *p=NULL;
2.小心指针越界情况,务必注意循环次数 。
3.指针使用前检查其有效性。
4.若指针空间被释放,将指针置成NULL。
打完收工!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)