自己的学习笔记视频在b站鹏哥C语言
指针是什么:
1. 指针是内存中一个最小单元的编号,也就是地址
2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
指针就是地址,口语中说的指针通常指的是指针变量
/*
char* p -->定义一个指针变量,该指针变量指向的是char类型的数据
int* p-->定义一个指针变量,该指针变量指向的是int类型的数据
*/
int main(void){
printf("%d\n",sizeof(char*));
printf("%d\n",sizeof(int*));
printf("%d\n",sizeof(float*));
printf("%d\n",sizeof(double*));
return 0 ;
}
输出结果:
4
4
4
4
原因:
对于32位的机器,假设有32根地址线:32/8=4(字节);那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。
注意:
对于指针就是存放地址的变量所有地址的大小和机器有关
会报warning:但是输出的地址是一样的,***指针的不同类型还是有具体意义的
在0x00EFFD98:这个地址这存储的是44 33 22 11 (这里为什么是反的是计算机组成原理的知识,大小端存储)。
当*pa=0时 0x00EFFD98:存储的内容都会变为00 00 00 00
当用char*pc=&a;*pc = 0时实际只改变了一个字节
所有不同的指针类型对与修改的内容大小是不一样的
注意:**指针类型决定了指针进行解引用操作的时候,能访问的空间大小**
int* p -->*p能够访问4个字节
char* p-->*p能够访问1个字节
double* p -->*p能够访问8个字节大小
指针+-整数
int main(void){
int a = 0x11223344;
int* pa = &a;
char* pc = &a;
printf("%p\n",pa);
printf("%p\n",pa+1);
printf("%p\n",pc);
printf("%p\n",pc+1);
return 0;
}
输出结果:
指针变量加减实际是加减的是类型的字节大小。
指针类型决定了:指针走一步走多远(指针的步长)
int* p -->p+1-->4
char* p-->p+1-->1
double* p -->p+1-->8
int arr[10]={0}
对于int* p =arr *(p+1)= 1;循环10次访问40字节,每次访问4个字节,所以会给10个元素都赋值成1因为是int类型指针变量
但是对于char*p =arr 循环10次访问10个字节,每次访问1个字节想当于给2.5个元素赋值1,因为是char类型的指针
野指针
野指针是指指针指向的位置是未知的(随机的,不正确的,没有明确限制的)
野指针成因:
1、指针未初始化
#include <stdio.h>
int main()
{
int *p;//局部变量指针未初始化,默认为随机值
*p = 20;
return 0;
}
2、指针越界访问
#include <stdio.h> int main() { int arr[10] = {0}; int *p = arr; int i = 0; for(i=0; i<=11; i++) { //当指针指向的范围超出数组arr的范围时,p就是野指针 *(p++) = i; } return 0; }
3、指针指向的空间释放
这段代码是错误的注意分析局部变量的生命周期和作用域就可以理解了,在出了test()函数后实际&a是不存在的,所以用指针访问就是错误的。
4、如何规避野指针
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放即使置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性
#include <stdio.h>
int main()
{
int *p = NULL;
//....
int a = 10;
p = &a;
if(p != NULL)
{
*p = 20;
}
return 0;
}