目录
一、指针是什么
指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值,由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”,意思是通过它能找到以它为地址的内存单元。
总结:
●指针就是变量,用来存放地址的变量。(存放在指针中的值都当做地址处理)
●指针的大小在32位平台是4个字节,在64位平台是8个字节
二、指针和指针类型
char* pa=NULL;
int* pb=NULL;
short* pc=NULL;
long* pd=NULL;
float* pe=NULL;
printf("%d\n",pa); //4
printf("%d\n",pb); //4
printf("%d\n",pc); //4
printf("%d\n",pe); //4
printf("%d\n",pf); //4
那么指针类型有什么意义呢?
●指针类型决定了指针解引用的权限有多大。char*类型指针解引用只能访问一个字节,int*类型指针解引用可以访问4个字节。
int a=0x11223344;
char* pa=&a;
*pa=0;
int* pb=&a;
*pb=0;
●指针类型决定了指针走一步能走多少(步长)
int main()
{
int arr[10]={0};
int* p=arr;
char* pc=arr;
printf("%p\n",p); //0x4FFC40
printf("%p\n",p+1); //0x4FFC44
printf("%p\n",p); //0x4FFC40
printf("%p\n",p+1); //0x4FFC41
}
三、野指针
野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
1、野指针成因
●指针未初始化
//1
int main()
{
int *p; //p是一个局部指针变量,不初始化的话,默认是随机值
*p=20;
return 0;
}
//2
int* f(void)
{
int* ptr;
*ptr=10;
return *ptr;
}
●指针越界访问
int main()
{
int arr[10]={0};
int* p=arr;
int i=0;
for(i=0;i<=10;i++)
{
*p=i; //当指针指向的范围超出数组arr的范围时,p就是野指针
p++;
}
return 0;
}
●指针指向的空间释放
int* test()
{
int a=10;
return &a; //return语句执行完后,a就会被释放
}
int main()
{
int* p=test();
*p=20; //非法访问内存
return 0;
}
2、如何规避野指针
●指针初始化
●小心指针越界
●指针指向空间释放及时指针置NULL
●指针使用之前检查有效性
四、指针运算
1、指针+-整数
#define N_VALUES 5
float values[N_VALUES];
float *vp;
for(vp=&values[0];vp<&values[N_VALUES];)
{
*vp++=0;
}
2、指针-指针
指针相减的前提是两个指针指向同一块空间。
两个指针相减得到的是两个指针之间的元素个数。
int my_strlen(char *s)
{
char *p=s;
while(*p!='\0')
{
p++;
}
return p-s; //得到的是两个指针之间的元素个数
}
3、指针的关系运算
第二种尽量避免。
因为C语言标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
//1
for(vp=&values[N_VALUES];vp>&values[0];)
{
*--vp=0;
}
//2
for(vp=&values[N_VALUES];vp>=&values[0];vp--)
{
*vp=0;
}
五、指针和数组
数组名是数组首元素的地址
int main()
{
int arr[10]={0};
printf("%p\n",arr); //0059FD48
printf("%p\n",&arr[0]); //0059FD48
return 0;
}
六、二级指针
1、概念
二级指针存放指针变量的地址
int main()
{
int a=10;
int* pa=&a; //pa是指针变量,一级指针
int** ppa=&pa; //pa也是一个变量,是二级指针,&pa取出pa在内存中起始地址
return 0;
}
2、 二级指针的运算
●*ppa通过对ppa中的地址进行解引用,这样找到的是pa,*ppa其实访问的就是pa
int b=20; *ppa=&b; //等价于pa=&b;
●**ppa先通过*ppa找到pa,再对pa进行解引用操作*pa,那找到的就是a
**ppa=30; //等价于*pa=30; //等价于a=30;
七、指针数组
指针数组是数组,是存放指针的数组!
int arr[10];//整型数组:存放整型
char ch[5]; //字符数组:存放字符
int* parr[10];//整型指针数组:存放指针