C初阶--指针初阶(上):什么是指针+指针类型+野指针(下)

简介: C初阶--指针初阶(上):什么是指针+指针类型+野指针(下)

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;
}

4022e04057ca4695843628cb81f70e51.png

从内存中看:可以发现数组一个元素就是一个int类型,一个元素占用4个字节的空间,那么10个就占用40个字节的空间

b84b5e6f31074c0384e4a44197de2ae4.png

图解:

010e6f17471744b0954c9cc278b45abb.png


1.修改成字符指针存放整型数组的地址

那么我们修改之后,改成以下这个样子,结果又会如何呢

c6a585882e6545efa1541ada54e49309.png

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;
}

2bb659fbedc8482eb86e52ed0bc4a0d1.png

图解:

9fbf28117b7b418cbfcb6ae23c6ed477.png

❗❗❗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的结果

ae242cc584eb41b3b58ce2df978724b6.png

还有,内存分布与写成int*p的指针也是一样的,它们没有区别吗?不,区别大了

50b2d60ad37044b084159369d618fa10.png

区别:特别注重!!!!!!✔️✔️✔️

6c57777720a74b5a827775f1f80e3ada.png

1.int *p=&arr[0] ,p++

308d9ec721534434bac64af4f607a2b9.png

这里是把绿色数字包括那部分全部占满了 

2.char* p=&arr[0],p=p+4

aed8ff44f37a40fcbca12fe65224fcc8.png

这里仅仅是把10个整型中每一个整型的第一个字节的数据改了,也就是上图中的黑色数字1234,并没有把每一个整型所占的4个字节全改完,还是有着本质区别的


3.野指针


概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)


3.1 野指针成因


1. 指针未初始化

#include <stdio.h>
int main()
{ 
 int *p;//局部变量指针未初始化,默认为随机值
    *p = 20;
 return 0;
}

767a70ba6f654e2cb8fd8bfba4edbd25.png

这里并没有有效的指向,按我的理解是正常逻辑是先&,生成指向该地址的指针,这才符合正常操作,而不是创建一个不知道明确指向的指针


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;
}


55981a5aca40448cae4c01e12cc6a91e.png

类比:就像有一条狗,它是有主人的,但有一天它走丢了,就是指向最后一个位置的时候,那它就是走丢了,它是一条野狗,变得非常危险


3. 指针指向的空间释放

int* test()
{
  int a = 10;
  return &a;
}
int main()
{
  int*p = test();
  *p = 100;
  return 0;
}


f23d42683f224f65b96def1991763e38.png

补充:局部变量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;
}

本章未完,还有下半篇....欢迎大佬补充!

相关文章
|
2月前
|
C语言 C++
【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5)
【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5)
|
3月前
|
存储 Go
Go: struct 结构体类型和指针【学习笔记记录】
本文是Go语言中struct结构体类型和指针的学习笔记,包括结构体的定义、成员访问、使用匿名字段,以及指针变量的声明使用、指针数组定义使用和函数传参修改值的方法。
|
4月前
|
存储 安全 Go
深入理解 Go 语言中的指针类型
【8月更文挑战第31天】
52 0
|
5月前
|
编译器 C语言
【C语言初阶】指针篇—下
【C语言初阶】指针篇—下
|
5月前
|
存储 C语言
【C语言初阶】指针篇—上
【C语言初阶】指针篇—上
|
6月前
|
编译器 C++
函数指针和函数对象不是同一类型怎么替换
函数指针和函数对象不是同一类型,为何可替换用作同一函数的参数
|
6月前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
53 0
|
6月前
|
图形学 Windows
程序技术好文:记录类型指针
程序技术好文:记录类型指针
29 0
|
6月前
指针初阶(2)
指针初阶(2)
32 0
|
6月前
|
存储 编译器 Perl
指针初阶(1)
指针初阶(1)
35 0