目录
1. 指针是什么?
指针理解的2个要点:
1. 指针是内存中一个最小单元的编号,也就是地址
2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
总结:指针就是地址,口语中说的指针通常指的是指针变量。
指针变量:
我们可以通过&(取地址操作符)取出变量的内存其实地址,把地址可以存放到一个变量中,这个 变量就是指针变量
#include<stdio.h>
int main()
{
int a = 10;//a是整型变量,占用4个字节的空间
int* pa = &a;
//pa是指针变量,用来存放地址
//本质上,指针就是地址
//口语中说的指针,其实就是指针变量,指针变量是用来存放地址的变量
//指针变量里面存放的是地址,而通过这个地址,就可以找到一个内存单元
return 0;
}
对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电 平(低电压)就是(1或者0);
那么32根地址线产生的地址就会是:
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
...
11111111 11111111 11111111 11111111
这里就有2的32次方个地址。
每个地址标识一个字节,那我们就可以给 (2^32Byte == 2^32/1024KB == 2^32/1024/1024MB==2^32/1024/1024/1024GB == 4GB)4G的空闲进行编址。
这里我们就明白:
在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以 一个指针变量的大小就应该是4个字节。
那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。
总结: 指针变量是用来存放地址的,地址是唯一标示一块地址空间的。
指针的大小在32位平台是4个字节,在64位平台是8个字节。
2. 指针和指针类型
这里我们在讨论一下:
指针的类型我们都知道,变量有不同的类型,整形,浮点型等。
那指针有没有类型呢? 准确的说:有的。
指针类型的意义1:
当指针类型是int*时,对pa解引用时,可以访问4个字节
当指针类型是char*时,对pc解引用时,可以访问1个字节
#include<stdio.h>
int main()
{
//0 1 2 3 4 5 6 7 8 9 a b c d e f
//0 1 10 11 100 …… 1010
//0001 0001 0010 0010 0011 0011 0100 0100
int a = 0x11223344;//十六进制,2个十六进制位代表一个字节
//一个十六进制位可以翻译成4个二进制位
//8个二进制位代表一个字节
//int* pa = &a;
//*pa = 0;
char* pc = &a;//编译器会报警告
//如果不想编译器报警告,可以将&a强制类型转换
//char* pc = (char*)&a;
//问:pc有没有能力存下a的地址?
//答:有,因为pc也是指针变量,占用4个字节,a的地址也是4个字节
*pc = 0;
//结论:指针类型决定指针在被解引用的时候访问了几个字节
//如果是int*的指针,解引用访问4个字节
//如果是char*的指针,解引用访问1个字节
//如果是double*的指针,解引用访问8个字节
return 0;
}
指针类型的意义2:
#include<stdio.h>
int main()
{
int a = 0x11223344;
int* pa = &a;
char* pc = (char*)&a;
printf("pa=%p\n", pa);
printf("pa+1=%p\n", pa + 1);
printf("pc=%p\n", pc);
printf("pc+1=%p\n", pc + 1);
//结论2:指针的类型决定了指针+或-1操作的时候,跳过几个字节;决定了指针的步长。
//int* 的指针 + 1——跳过4个字节;
//char* 的指针 + 1——跳过1个字节;
//double* 的指针 + 1——跳过8个字节。
//加减不仅可以是,还可以是任意的整数,比如int*的指针类型+2,表示跳过了8个字节
//当我们希望指针访问内存空间时,一个字节一个字节的访问时,我们可以使用char*指针
//同理,当希望4个字节4个字节的访问时,可以使用int*的指针
//可以通过类型转换,转换成我们需要的指针
return 0;
}
指针 + - 整数
总结:指针的类型决定了指针向前或者向后走一步有多大(距离)。
指针的解引用
总结: 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。
比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。
注意:
分析:
所以,两个指针类型不能混用。
#include<stdio.h>
int main()
{
int a = 0;
int* pi = &a;//pi解引用访问4个字节,pi+1跳过4个字节
float* pf = &a;//pf解引用访问也是4个字节,pf+1也是跳过4个字节
//问:int*和flaot*是不是就可以通用?
//答:不是。因为站在pi的角度,它认为它指向的内存里面放的是整型的数据
// 站在pf的角度,它认为它指向的内存里面放的是浮点型的数据
//*pi = 100;
*pf = 100.0;
return 0;
}
3.野指针
野指针概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
野指针成因
1)指针未初始化
2)指针越界访问
当指针指向的范围超出数组arr的范围时,p就是野指针
3)指针指向的空间释放
如何规避野指针
1)指针初始化(当不知道给指针初始化为什么时,可以给它赋NULL(0))
那如果想给*p2赋值,该如何写呢?
如果p2真的不是空指针,说明它已经有明确的指向了,这时候我们可以使用它了。
2)小心指针越界
3)指针指向空间释放即使置NULL
4)避免返回局部变量的地址
5)指针使用之前检查有效性