3.指针类型的意义用处在哪呢?
以下的1和2的知识点是连贯的☑️
以往的知识我们可以知道,访问数组元素可以用数组名+下标例如:arr[1]来访问数组元素
也可以用*(p+i)的形式给数组元素赋值👇👇
int main() { int arr[10] = {0}; int* p = &arr[0]; int i = 0; for (i = 0; i < 10; i++) { *p = i + 1; p++; } for (i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0; }
从内存中看:可以发现数组一个元素就是一个int类型,一个元素占用4个字节的空间,那么10个就占用40个字节的空间
图解:
1.修改成字符指针存放整型数组的地址
那么我们修改之后,改成以下这个样子,结果又会如何呢
int main() { int arr[10] = {0}; char* p = &arr[0]; int i = 0; for (i = 0; i < 10; i++) { *p = i + 1; p++; } for (i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0; }
图解:
❗❗❗2.关于整型指针和字符指针赋值后执行结果一样的本质原因❗❗❗
注意区别:
int main()
{
int arr[10] = {0};
char* p = &arr[0];
int i = 0;
for (i = 0; i < 10; i++)
{
*p = i + 1;
p=p+4;//这个位置修改了
}
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
就会发现,得到神似int* p的结果
还有,内存分布与写成int*p的指针也是一样的,它们没有区别吗?不,区别大了
区别:特别注重!!!!!!✔️✔️✔️
1.int *p=&arr[0] ,p++
这里是把绿色数字包括那部分全部占满了
2.char* p=&arr[0],p=p+4
这里仅仅是把10个整型中每一个整型的第一个字节的数据改了,也就是上图中的黑色数字1234,并没有把每一个整型所占的4个字节全改完,还是有着本质区别的
3.野指针
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
3.1 野指针成因
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. 指针指向的空间释放
int* test() { int a = 10; return &a; } int main() { int*p = test(); *p = 100; return 0; }
补充:局部变量a出了它所在范围就销毁了
3.2 如何规避野指针
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放,及时置 NULL
4. 避免返回局部变量的地址(上一题,局部变量a出了它所在范围就销毁了)
5. 指针使用之前检查有效性(记得对指针初始化,有明确指向的时候给它初始化,没有明确指向的时候,给它初始化为NULL指针)
案例:正确使用
int main() { int a = 10; int* p = &a; //一个指针不知道应该指向哪里的时候,暂时可以初始化为NULL; //int* p = NULL; if (p != NULL) { *p = 100; } return 0; }
本章未完,还有下半篇....欢迎大佬补充!