从零开始的指针的应用2--符号

从零开始的指针的应用2--符号、野指针


前言:一个人不需要很聪明,他只要守规矩,肯努力就可以了(不是自己感动自己的那种)

           因为我们的前期目标只是获得比较客观的月薪就行了,我们不用去拿诺贝尔奖。

           也就是说,这还轮不到拼智商的时候。


参考:朱有鹏大讲坛的C语言高级专题


1、指针的符号

      前面我已经说过了,编译器是啥都不懂的东西,我们需要编程去控制,

      但是有些时候,编译器会反过来“编程”我们,因为你自己连编程的基本规则都不懂


      做任何事情都需要规则,没有规则就没有任何意义,那么编译器的规则我们是否要去理解

      有时间的,我觉得是非常必要去理解的,因为我们编程的目的就是让编译器听我们的指令。

      首先,规则的编写就是符号。哪些符号是编译器理解的,哪些符号是你自己编造的?

      都要认真的理解,这些都不知道,学后面就是在自己感动自己


2、指针的规则和符号:

   

星号*

1)在C语言中*可以表示乘号,也可以表示指针符号。

 

这两个用法是毫无关联的,只是恰好用了同一个符号而已。

 

(2)星号在于用于指针相关功能的时候有两种方法

 第一种是指针定义时,*结合前面的类型用于表明P的类型是int *也就是P是指向int类型的指针。

第二种功能是解引用,解引用时,*p表示p指向的变量的本身。演示指针变量的解引用。


要理解它是什么作用的话,那么就有所谓的上下文了,所以说高考语文叫你考的阅读理解就是有用的,

因为有时候,一个词语可以代表的东西很多,需要通过上下文来理解。


我对此也有自己的理解:*号既然有两种表达方式:

           首先可以看看下面的程序

            第一个*号代表的是定义数据类型,定义一个整型的变量,因为它旁边有一个int的数据类型

            第二个*号代表的是取内容,取这个指针指向空间的内容。

            因为指针也是一个变量,所以我们如果仅仅调用它自己的话,那么p代表的是它自己指针

            当加上*p之后,代表就不是这个指针了,打个比方int a;  你可以用a来代表一个变量。

            但是你如果向a加上一个前缀&,那么它就不是原来的意思了。

            所以*p就不代表指针了,代表的是指针指向跟它绑定空间的内容。

           

#include <stdio.h>

int main(void)
{
     int a= 24;
     int *p ;
     p = &a;
     *p = 5;
     printf("");      //这里自己填入自己想要打印的东西
     return 0;
}

3、取地址符&

    就如同上面讲的内容一样,这个是C语言规定的


4、左值和右值的区别:

(1)放在赋值运算符左边的就叫左值,右边的就叫做右值,所以赋值操作其实就是左值 = 右值的一种运算。

 (2)当一个变量做左值时,编译器认为这个变量符号的真实含义是这个变量所对应的内存空间

(3)当一个变量做右值时,编译器认为这个变量符号的真实含义是这个变量真实的值。所对应空间中存储的数


    

5、野指针

野指针就是指针指向的位置是不可知的

(随机的,不正确的、没有明确限制的)

 

 

运行时的段错误就是因为野指针造成的。

 

(2)野指针很可能触发运行时的段错误(sgmentation fault)

(3)因为指针变量在定义时未初始化,值也是随机的,指针变量的值其实就是别的变量,所以意味着这个指针指向了一个地址不确定的变量,这时候去解引用就是去访问这个地址不确定的变量。

 

 

(4)野指针因为指向的地址是不可预知的,所以有三种情况

 

第一种:就是指向不可访问的地址(操作系统的内核空间)

 

(每一个进程都以为自己有4G的空间)

 

进程访问的空间里面有一段是操作系统里面的。结果就是触发段错误。

 

这种算是最好的情况。

 

第二种:指向一个可用的、而且没有什么特别意义的空间,比如我们曾经使用过的栈和堆空间。这时候,程序的运行不会出错,也不会对当前程序造成损害。

这种情况下会掩盖你的程序的错误,让你以为程序没有问题,其实是有问题的。

 

 

第三种情况,就是指向了一个可用的空间,而且这个空间正在被使用。

 

那么野指针的解引用就会刚好修改这个变量的值,导致这个变量

一般最终都会导致程序奔溃,这种危害最大的。

 

就决定了栈的使用多少会影响这个默认值。因此野指针的值是有一定规律不是完全随机,但是这个值的规律对于我们来说是没有任何意义的,因为不管落在上面野指针三种情况的哪一种,都不是我们想看到的。

 

 

 

2、怎么避免野指针

(1)野指针的错误来源就是指针定义了以后没有初始化,也没有复制。

 

没有指向一个可用的内存空间,然后去解引用。

2)知道了野指针产生的原因,避免方法就出来了:在指针解引用之前,一定确保指针指向一个绝对可用的空间。

 

(3)常规的做法就是这样

   第一步:定义指针时,同时初始化为NULL

      int *p = NULL;

   第二步:在指针解引用之前,先去判断这个指针是不是NULL;

    ........

     if(NULL != p)

     {

          .....

     }

   第三点:在指针使用完毕之后,将其赋值为NULL;

          p =NULL;

 

第四点:在指针使用之前,将其赋值绑定给一个可用地址空间

          这个步奏本来应该是在前面的

          int  a = 34;

          p = &a;

 

正确的使用指针的方式,是解引用指针前跟一个绝对可用的地址绑定。

 

不用的话,把它的值设为NULL,用的时候判断是否为NULL

 



















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值