赞
踩
从零开始的指针的应用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;
- }
就如同上面讲的内容一样,这个是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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。