1.指针与指针变量
– 为什么有指针?
我们知道一般计算机能做运算的元器件是CPU,而数据是保存在内存中的。当需要进行运算时,计算机需要将数据从内存拿到CPU的寄存器中。为了方便CPU可以直接在保存数据的内存中直接拿到数据于是引入了指针。
– 指针是什么?
指针就是地址。数据就保存在该地址的内存中。
– 什么是指针类型?
指针类型是一种新类型,它的表现形式为
类型+
*
常见的指针类型有:
int * //整形指针类型
char *//字符指针类型
float *//单精度浮点指针类型
double *//双精度浮点指针变量
– 什么是指针变量?
指针变量就是指针类型定义的变量。例如:
int *a=NULL;//定义一个整形指针变量 a
char *p=NULL;//定义一个字符指针变量 p
– 指针大小?
在32位平台下指针占4字节,在64位平台下指针占8字节。
原因:拿32位平台举例。在32位平台的计算机中连接CPU与内存有32根地址总线,每一根线有两态0和1,32根线两态的不同组合组成了内存的地址,所以在32位平台下内存有2^32次方=4GB大小。所以一个字节地址由32比特位组成,而一个直接由8比特位组成,所以一个地址占4字节,由于指针就是地址,所以指针占4字节。
注意:在32位平台下,所有类型指针占4字节。同理在64位平台下,所有类型指针占8字节。
– 指针类型作用?
由于指针的大小是确定,那为什么要定义指针类型呢?
下面列一个例子来展示。
#include<stdio.h>
int main(){
int n = 10;
char *pc = (char *)&n;//将n的地址强转为char *类型
int *pi = &n;
printf("%p\n", &n);
printf("%p\n", pi);
printf("%p\n", pc);
printf("%p\n", pi+1);
printf("%p\n", pc+1);
return 0;
}
输出:
由上可知,int n占4字节,应该有4字节的地址。&n和指针取的地址为n的最小的地址,所以&n,pi和pc显示出来的地址相同。而我们发现pi+1和pc+1的地址是在原有的基础上加4和1,这就说明,
指针的类型决定了指针向前或者是向后的跨度
。跨度为sizeof(不带*类型)的大小。
– 指针解引用
对指针进行解引用代表指针存放的地址的目标。
int a=10;
int *p=&a;
此时的*p就是a。
注意: 指针进行解引用能操作几个字节也有指针类型决定。
如果定义一个int a将它的4字节全部写入数字,用一个整形指针类型的指针变量指向这个整形变量,对这个指针变量的解引用赋值时,这个整型变量4个字节都会发生改变,如果用一个字符指针类型的指针变量指向这个整形变量,对这个指针变量的解引用赋值,这个整型变量只有2个字节的发生变化。
– 指针的运算
主要讲指针的减法运算:前提必须是两个指针指向同一数组。
#include<stdio.h>
int main(){
int n[5] = { 1, 2, 3, 4, 5 };
int *ps = &n[4];
int *pi = &n;//&n[0];
printf("%d\n", ps - pi);
return 0;
}
输出为
4
输出原因:当两指针相减结果为两指针之间元素个数。
解释:由于数组n为int,每个元素占4个字节。pi指向的是n[0]的最小地址,ps指向n[4]最小地址。pi与ps之间一共有16个字节,但是每个元素类型为int*占4个字节,所以显示为4.
将上面代码改一下类型发现:
#include<stdio.h>
int main(){
int n[5] = { 1, 2, 3, 4, 5 };
short *ps = &n[4];//将n的地址强转为short *类型
short *pi = &n;
printf("%d\n", ps - pi);
return 0;
}
输出为:
8
由上知pi与ps之间有16字节,但是ps与pi被强转为short *类型使得每个元素占2字节。所以输出为8.
由上得出结论:在两指针指向同一数组的前提下,指针相减表示两指针之间的元素个数,具体元素个数由指针类型决定。
2.野指针
– 概念
野指针指指针指向的地址不可知(随机,不正确,没有明确限制)。
– 形成原因
- 指针未进行初始化
- 指针访问越界
- 指针指向的空间释放
3.指针和数组
指针与数组并没有关系,只是当一个指针指向一个数组时他们进行元素访问的方式相同。前提:数组类型与指针去*后的类型相同。
int a[3]={1,2,3};
int *p=a;//a数组首元素的地址。
此时就有:a[i]=*(a+i)=p[i]=*(p+i)。
4.二级指针
由于指针变量也是变量就需要开辟空间,就会有地址。而二级指针就是存放一级指针地址的指针。
表现形式:
int **a
char **b
float **c
...
形成格式为:类型+*+变量名。拿int **a举例-> 整形指针类型+*+a。
int a=10;
int *pa=&a;
int **ppa=&pa;
此时ppa存放的pa的地址,*ppa等于a的地址,**ppa等于a。
5.指针数组
指针数组实际上是数组,只是里面的元素都是指针。
表现形式:
int *a[5];
char *b[3]
float *c[2];
....