1.指针是什么?
指针是内存中最小单元的编号,也就是地址。
平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量。
如果一个变量的大小不止一个字节,他的地址就是他所占内存的第一个字节的地址。
指针变量的大小:在32位机器上,有32根地址线,每根地址线有高电平和低电平两种状态,也就是1和0两种状态,而三十二根地址线总共能给2^32个地址编号,每个内存单元为一个字节,总共就能管理4gb的内存。当我们要用一个变量将地址存储起来时,就需要三十二个比特位,也就是四个字节的空间。所以在三十二位机器上,指针变量的大小是四个字节。
相同的,在六十四位机器上,有六十四跟地址线,所以指针变量的大小为8个字节。
总结:指针变量是用来存放地址的,地址是唯一标示一块内存空间的。
指针的大小在32位平台上是四个字节,在64位平台是8个字节
2.指针和指针类型
指针类型就是指向的对象的类型加个*
int *,char *,short *,float *,long *,double *……
上面我们说到指针的大小是一样的,那为什么要分类型呢?
我们首先知道,不同类型的变量在内存中存储的方式是不一样的,所占内存大小也是不一样的,我们创建指针的目的最终还是要通过指针来访问指针指向的对象,虽然指针变量的大小是一样的,但是他们访问的权限和访问内存的方式是不一样的。1.指针类型决定了指针的权限,也就是指针被解引用时访问的内存的大小。如果是 int*类型的指针解引用时访问四个字节的空间,char*指针解引用时访问一个字节。 2.不同类型的指针进行加减整数的运算时跳过的内存大小也是不一样的,char*的指针加一时跳过一个字节,而int*的指针加一时跳过四个字节。在比如,虽然int *和float*的指针都能访问四个字节,访问权限和加减整数跳过的大小也是一样的,但是因为他们在内存中的存储不一样,当我们对跟指向的对象不同类型的指针解引用修改指向的对象时,是以该指针的类型来决定用什么方式修改的。假如我们用一个float*的指针来存储一个整型的地址,对他解引用进行修改时,会以浮点型的存储方式放进指向的对象中,而当我们以整型的方式打印对象时,达不到我们想要的效果。
3.野指针
野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
野指针成因
1.指针未初始化。
当一个指针变量不初始化的时候,放的是随机值,就意味着没有明确的指向。当我们对这个未初始化的指针进行访问时就是非法访问内存了,这时候这个指针就是野指针。
2.数组越界访问。
在我们用指针访问数组时,超出数组范围的访问就是越界访问。当指针超出数组范围的时候就成了野指针。
3.指针指向的空间释放。
比如一个函数中的临时变量的指针如果传回主函数中,函数栈帧销毁后,如果再使用这个指针就是野指针。
然后避免野指针?
1.创建指针的时候就直接初始化,如果当前还不明确指针对象就初始化成空指针NULL。
2.小心指针越界
3.指针指向的空间释放就及时把指针置为空指针。
4.避免返回局部变量的地址
5.指针使用之前检查指针的有效性
4.指针运算
1.指针+-整数
跳过或者后退整数个指针所指向的类型的空间
我们可以用这种方式给数组赋值。
2.指针-指针
指针减指针得到的数值的绝对值时指针与指针之间的元素个数。
不是所有的指针都能相减,指向同一块空间的两个指针才能相减,只有这样才是有意义的。
我们可以用这个运算来求字符串的长度,用'\0'的地址减首元素的地址。
4.3指针的关系运算
关系运算也就是比较大小
> ,<,>=,<=,==
指针的关系运算可以用来给数组赋值时当作循环的条件
在上面这段代码中,我们用到了arr[10]来作为循环终止的条件,那我们可不可以从arr[9]开始往前赋值呢,这样可不可以用arr[-1]作为循环终止条件呢?
这时候编译器会给我们报一个这样的错误,程序也无法达到我们想要的效果
为什么我们可以比较arr[10]却不能比较arr[-1]呢
这是因为标准规定:允许指向数组的指针与指向最后一个元素后面的那个内存位置进行比较,但是不允许与指向第一个元素之前的那个内存的位置的指针进行比较
意思就是比较的时候允许向后越界,不允许向前越界。
5.指针与数组
在上面我们的举例中我们能做的,数组是可以通过指针来访问和赋值的。
6.二级指针
int a=10;
int* pa=&a;
int* *pa=&pa;
在上面的代码中,pa是一个指针变量,定义的时候 * 可以理解为说明pa是个指针变量,int表示pa所指向的对象类型是int类型的。同时pa是一个一级指针变量,只需要解引用一次就能访问到a的内容。
ppa也是一个指针变量,ppa要访问a的内容要经过两次解引用,第一次解引用访问到pa的内容,再对pa的内容解引用访问到a的内容,所以ppa是一个二级指针。 int*表示ppa所指向的对象是一个int*类型的,第二个* 则表明ppa是一个指针变量。
7.指针数组
前面我们讲到数组是相同类型元素的集合
那我们是不是可以说,相同类型的指针变量也可以存到数组中呢,答案当然是肯定的。
当有了存放指针的数组,我们就可以用指针数组来模拟实现二维数组。
在这篇文章中我们只讲了指针的简单介绍,指针的高阶用法后续会继续发文补充。