什么是指针,指针类型,指针变量,指针类型 内存 野指针
Part1:
内存,指针概念,小格子,编号,地址,如何编号,格子多大,电信号,数字信号,一字节,内存单元
什么是指针,在这之前要先了解内存,内存是计算机内用来存储的物质,为了方便,我们将其按一字节一字节分为许多个小格子,按照电信号转化为的数字信号对其进行编号,这些编号被称为地址。根据地址我们可以找到相应的小格子,也就是内存单元,地址由于该特性被称为指针,找格子的这个操作也被称为“指针的解引用”,也就是“*”这个符号。
Part2:
指针类型,存放编号,指针变量,地址处理,32位,寻址线,指针大小
我们将地址当成值来保存在一个变量中,这个变量就是指针变量,指针变量和其他变量并没有什么不同,都是用来保存值的一个空间,只不过它保存的是指针(地址),有一点要注意,指针变量所占据的空间是确定的。因为该空间用来存放地址,32位系统有32根寻址线,可分为2的32次方个内存单元,所以其所占空间为4字节,同理64位占8字节。
Part3:
区分类型,字节占用,进制占用,不同可存
因为指针变量是一块长度固定的空间,那么只要是一个地址就都可以存放进去,那么指针分类型的意义是什么?在这之前先了解一下进制
进制占用,一个二进制占用一个bit,简称位,八位为一字节,十六进制占四位,地址就是用十六进制来表示的(因为二进制太长了),但指针变量又说存放地址绰绰有余,不应该是刚刚好可以存放吗,四个字节存放32位,刚刚好呀。
Part4:
类型意义 找格子 加减整数
指针类型不同在存放时没有任何区别,都是一个小格子的地址,但在根据地址找到格子(解引用)的时候区别就来了,不同类型的指针找到的格子数不一样,char*只能找到一个格子,int*可以找到四个格子(根据地址找到第一个,在往后找三个)(在定义char或者int变量的时候,系统本就会为其分配空间,这里令指针刚好找完该空间),如果要对格子里(内存单元)的数据修改,就要先找到它。同时指针加减整数的时候,并不是在十六进制上加减该整数,与指针变量类型有关,char*是往后找一个格子,int*是往后找四个(这里指第一个格子往后的四个,换个方式理解:就是四个四个往后找,跳过),PS:格子就是内存单元,大小为一个字节,可以自己尝试定义指针变量,对指针变量进行++,然后和原本指向的相减,得到的值就是格子数,内存单元数,字节数被处理后的元素个数(格子数除于元素占据的格子数)。
Part5:
数组名,整型移动char,野指针,局部变量,初始化,越界访问,指针空间释放
数组名就是一个地址,可以直接赋给指针变量(放到那个空间里去),一个整型四个字节,在内存中用十六进制显示给我们看(两位十六进制是一字节),如果开始整型为
00 00 00 00 ,00 00 00 00.(包含两个int的数组){0,0}定义一个某类型指针指向该数组(p)并*++p=1,等价于p=p+1;*p=1;
00 00 00 00 ,01 00 00 00(int*)值为{0,1}
00 01 00 00, 00 00 00 00(char*)值为{16*16,0}
野指针就是指针变量里边的指针(地址)不确定,是指向任意一个位置的。
危害:由于其内的地址是不确定的,所以对其进行解引用,会出现很大的问题,也许你的系统被更改后就崩溃了。
可以产生野指针的操作:
- 未初始化,像定义一个局部变量未初始化一般,那个空间里放的是09 98 a3 4b(int)(之前遗留下的数),局部指针变量也是如此,如果那块空间内本就有一些数,就会默认是该变量的指针。
- 越界访问:定义了一个整型或者整形数组,这个时候系统会为其开辟一片空间给它使用,将空间地址放入一个指针变量,·对其做了整数加减,使得最后内存单元的地址并不是原来那块空间的,即超出了这块空间。
- 指针空间释放:比如在某个函数中,你在其中定义了一个局部变量,并返回其地址,函数返回后局部变量所在空间被释放,但其地址被存放在一指针变量中,野指针就产生了。还有动态内存那块,如果直接将获取的内存释放,其地址还是被我们获取的,野指针就产生了
- 总结:有一个指向不知道哪里的指针。
对应的方法:按照能产生野指针的步骤来
- 定义一个指针变量后就对其进行初始化。
- 对指针进行变换时,注意其是否越界。
- 返回地址时,注意该空间是否还是该程序的。
- 释放地址时,将指向该空间的指针指向NULL
- 访问地址时注意其是否有效。