指针
核心
本质上指针就是地址
概念理解:
内存单元的编号就是地址(指针)
口语中的指针,其实是指针变量是用来存放内存地址的变量
1
2
3
4
5int main(){
int a=0;
int* pa =&a;//pa用于存放a的值 类型为int *
return 0;
}结论
指针变量 里面存放的是地址,通过这个地址,能够找到一个内存单元
在32位的机器上,有32个地址线,能够编译2的32次方的地址
- 指针在32位机器上是4个字节
在64位的机器上,有64个地址线,能够编译2的64次方的地址
- 在64位机器上指针为8个字节
指针类型
1
2
3
4int a=10;
int *pc=&a;
char *pi=&a;
double *pl=&a;在内存中我们知道
- 指针变量所占的字节大小取决于该机器所配备的位数
那么思考:
为什么我们需要为指针设置那么多的类型?而不直接创建一个总的指针来定义?
实际意义
1
2
3
4int a=0x11223344;//16进制的数字
int* pc=&a;//指针变量存放地址
*pc=0;//地址所找到的那个值进行修改为0
//最终四个字节的位置都被改变为了01
2
3
4int a=0x11223344;
char* pc=(char *)&a;//强制类型转化为字符指针变量
*pc=0;
//最终只有一个字节的位置被修改为了0如果int*的指针,指针访问4个字节
如果char*的指针,指针访问1个字节
结论1
指针类型决定了指针在被解引用时访问几个字节
但是不决定指针变量所占的字节大小
1
2
3
4
5
6
7int a=0x11223344;
int *pc =&a;
char* pq =(char*)&a;
printf("%p",pc);//地址--首元素的地址
printf("%p",pc+1);//跳过了四个字节的指针步长
printf("%p",pq);//地址--首元素的地址
printf("%p",pq+1);//跳过了一个字节的指针步长结论2
指针的类型决定了指针+1或 -1操作时,跳过几个字节
决定了指针的步长
理解
指针变量的大小与机器位数相关,指针变量指向的那个空间即为内存所决定的大小由它的类型所决定
指针变量是存储地址的 而它的访问权限取决于该数据变量的类型
类型有多大 可访问该数据变量的字节也会随之增大
野指针
不赋初值
- 错误演示
1
2int* p1;//未为指针变量赋初值
*p1=10;//非法访问指针变量存放的地址对应的值 因为p1为指针变量 在内存中有很多块空间 如果不赋初值 会导致指针指向发生错误
当不知道给指针赋什么值时 我们采用空指针赋值给指针变量
1
2
3
4int * p=NULL;//赋予空指针
if(p!=NULL){
*p=20;
}//需要判断此指针不为空指针这里需要用判断语句 判断该指针是否为空指针 如果不为空指针 才能对指针里的变量进行修改
指针指向的空间释放
- 错误演示
1
2
3
4
5
6
7
8
9
10
11
12
13//局部变量的生命周期
//在所限定的代码块区内部 出了代码块区 则这个局部变量会被销毁
int *test(){
int a=10;//a为局部变量
//在test函数可以使用,但是a出了该函数会被销毁
return &a;
}
int main(){
int *p=test();
//指针变量能够找到该变量地址
//但是不能访问
return 0;
}指针下标越界
- 错误演示
1
2
3
4
5
6
7int arr[10]={0};
int i=0;
int *p=&arr;//首元素地址
for(i=0;i<=10;i++){
*p=i;
*p++;//此时会发生指针下标越界,访问不到下标为10的值
}结论
为防止野指针的出现,我们采用以下几点:
对与指针变量赋初值
- 当然,可以采取赋空指针的方法–防止指针指向错误
注意下标越界问题,思考该数组的元素个数
调用函数使用指针时,避免返回局部变量的地址