【C语言入门】由浅入深学习指针 【第二期】

打印 上一主题 下一主题

主题 1752|帖子 1752|积分 5256

 
目录
 1. 指针变量为什么要有类型?
2. 野指针
2.1 未初始化导致的野指针
2.2 指针越界导致的野指针
2.3 怎样规避野指针 
3. 指针运算
3.1 指针加减整数
3.2 指针减指针
3.3 指针的关系运算
4. 二级指针
5. 指针数组
5.1 怎样使用指针数组模拟二维数组
           上一期已经解释了指针和指针变量的区别以及含义,这一期我们来具体相识一下指针到底有什么作用。
   1. 指针变量为什么要有类型?

        我们知道指针变量的大小是根据地点平台决定的,若平台是32位即x86环境,则指针变量是4个字节,若平台是64位,则指针变量是8个字节。既然指针变量不会根据指针类型变革,那么我们为什么要区分指针变量的类型呢?换句话说char* 和 int* 都有能力存储4个字节的地址,为什么不统一成一个自定义的指针变量例如ptr*

        从上图可以得知,我们把int*类型的地址强行赋给char*类型的地址,再举行取值调用的时候,会根据char*来举行赋值以至于只会将一个字节赋值成0,如果正常使用int*来接收,那么四个字节都是0 ,如下图所示。


        由下图可知,虽然不同指针变量的存储类型不影响地址的存储,但是当直接对地址举行运算,还是会根据指针类型的不同举行运算。char*类型+1,跳过1个字节,int*类型+1,跳过4个字节。

所以我们会得到这样的结论:指针变量的类型在存取地址的时候可有可无,在修改地址指向的内容的时候是非常有必要的,它决定了在利用地址更改值的时候必要更改多少个字节;若直接对地址举行运算,那么会根据指针变量的类型+‘1’,这个‘1’大概是char类型的一个字节,也大概是int类型的四个字节。 

使用float*和int*的时候,无论是访问内存还是使用内存,都是4个字节,那么可不可以混用呢?
答案是:不可以
下图是整型解引用赋值整型,我们可以看到100以16进制存入内存。

我们把100.0存入内存,发现内存存的数据发生了变革, 虽然都是100,但是浮点数存入内存的方式是不同的。


2. 野指针

        指针指向的内存没有初始化,大概已经被销毁,此时的指针称为野指针。
2.1 未初始化导致的野指针


2.2 指针越界导致的野指针



2.3 怎样规避野指针 

①指针初始化。
②指针小心越界。
③指针指向的空间置为NULL。NULL是0,类型是void*,如果取值的话一定会报错(默认0地址不能访问),所以,我们可以先判断这个指针如果不是NULL再举行取值。


④制止返回局部变量的地址,由于局部变量已经被销毁了(没有那块内存空间的使用权限了)。
⑤指针使用之前检查有效性。

3. 指针运算

3.1 指针加减整数

这里的values[N_VALUES]并不算下标越界,由于并没有使用这段内存,只是用了一下这个地址作为判断条件。

3.2 指针减指针

当同类型的地址减去同类型的另外一个地址,得出的结果的绝对值是两个地址之间的元素个数


必要注意的是,两个指针指向的必须是同一块内存,否则毫无意义。


        那么有同砚会想,指针+指针得到的结果是什么呢,这个结果毫无意义,类似于你可以把日期相减,得到天数,但是你不能把日期相加,这样就毫无意义
3.3 指针的关系运算

实在就是地址之间的比较,判断两个地址谁大谁小,从而对地址指向的内容举行操作。


4. 二级指针

        简单描述一下,就是指针变量里面存的地址,这个地址是一个指针的地址。乍一听是不是以为在说绕口令呢?下面用一张图来举行诠释。

        上图中表现int * pa = &a;我们可以这么明白:*号表明pa的类型是一个指针类型,int表明这个指针类型指向的是int类型;那么我们是不是可以来明白一下二级指针。

        int* *ppa = &pa;还是将类型拆开,间隔ppa最近的*表明ppa是一个指针,int* 表明ppa指向的类型是int*的类型
总结:二级指针是用来存放一级指针变量的地址
5. 指针数组

主语是数组,即存放指针的数组就是指针数组


5.1 怎样使用指针数组模拟二维数组

        首先构造出三个一维数组,所谓二维数组就是将这三个一维数组连起来;我们构造一个指针数组,分别存入之前构造的一维数组名,在之前的帖子说明,一维数组名是数组的第一个元素的地址,所以分别存入了三个地址,我们必要遍历指针数组,得到三个一维数组的首地址,再引入一个变量j,根据指针加减法,就可以访问一维数组中除了第一个元素的其他元素的地址,最后解引用就可以得到最后的结果。
  1. #include <stdlib.h>
  2. int main()
  3. {
  4.     int arr1[4] = {1,2,3,4};
  5.     int arr2[4] = {2,4,6,8};
  6.     int arr3[4] = {3,6,9,12};
  7. // 用一维数组模拟出二维数组的效果
  8.     int* arr_sum[3] = {arr1,arr2,arr3};
  9.     for(int i = 0;i < 3;i++)
  10.     {
  11.         for(int j = 0;j < 4;j++)
  12.         {
  13.             printf("%d ",*(arr_sum[i] + j));
  14.         }
  15.         printf("\n");
  16.     }
  17.     return(0);
  18. }
复制代码



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

火影

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表