高级C语言-指针

指针到底是什么?

指针到底是什么?
首先必须非常明确:指针的实质就是个变量,他和普通变量没有任何本质区别。指针完整的名字应该叫指针变量,简称指针

int a;//定义了一个int型变量,名字叫a
int *p;//定义了一个int * 类型的指针变量,名字叫p,指向了一个int型变量
a = 4;//编译器可以操作
p = 4;//编译器不允许操作,因为指针变量虽然实质也是普通变量,但是它的用途和普通变量不同。
//指针变量存储的应该是另外一个变量的地址。而不是用来随意存储一些int类型的数
p = (int *)4;//我们明知道这个就是普通数字4,但是我强制类型转换成int * 类型的4;
//相当于我告诉编译器,这个4其实就是地址(而且是int类型变量的地址),那么(int *)4就和p类型相匹配

为什么需要指针?
(1)指针的出现是为了间接访问。在汇编中都有间接访问,其实就是CPU的寻址方式中的间接寻址
(2)间接访问(CPU的间接寻址)是CPU设计时决定的,这个决定了汇编语言必须能够实现间接寻址,又决定了汇编之上的C语言也必须实现间接寻址
指针使用三部曲:定义指针变量,关联指针变量,解引用
(1)当我们int *p 定义了一个指针变量p时,因为p是局部变量,所以也遵循C语言局部变量的一般规律(定义局部变量并且未初始化,则值是随机的),所以此时p变量中存储的是一个随机的数字
(2)此时如果我们解引用,则相当于我们访问了这个随机数字为地址的内存空间。那这个空间到底能不能访问不知道,所以如果直接定义指针变量未绑定有效地址就去解引用几乎必死无疑
(3)指针绑定的意义在于:让指针指向一个可以访问,应该访问的地方

//指针使用的3步:定义指针变量,给指针变量赋值(绑定指针),解引用
int a = 23;
//第一步:定义指针变量
int *p;
//第二步:绑定指针,其实就是给指针变量赋值,也就是让这个指针指向另一个变量
//当我们没有绑定指针变量之子安,这个指针不能被解引用
p = &a;				//实现指针绑定,让p指向变量a
p = (int *)4;		//实现指针绑定,让p指向内存地址为4的那个变量
//第三步:解引用
*p = 555;			//把555放入p指向的变量中

指针带来的一些符号理解

(1)指针定义时可以初始化,指针的初始化其实就是给指针变量初值(普通变量的初始化没有任何本质区别)
(2)指针变量定义同时初始化的格式是:int a = 32;int *p = &a;
(3)不初始化时指针变量先定义再赋值:int a = 32;int *p; p = &a;
左值与右值:
(1)放在赋值运算符左边的就叫左值,右值得就叫右值。所以赋值操作就是:左值 = 右值
(2)当一个变量做左值时,编译器认为这个变量符号的真实含义是这个变量所对应的内存空间;当一个变量做右值,编译器认为这个变量的真实含义就是这个值,也就是这个变量所对应的内存空间中存储的那个数

野指针问题

什么是野指针?哪里来的?危害?
(1)野指针,就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
(2)野指针很可能触发运行时段错误(segmentation fault)
(3)因为指针变量在定义是如果未初始化,意味着值是随机的。指针变量的值其实就是别的变量(指针所指向的那个变量)的地址,这个指针指向了一个地址是不确定的变量,这时候去解引用就是去访问这个地址不确定的变量,所以结果是不可知的。
(4)野指针因为指向的地址是不可预知的。所以有三种情况:第一种是指向不可访问(操作系统不允许访问的敏感地址,譬如内核空间)的地址,结果是触发段错误。第二种:指向了一个可用的,而且没有什么特别意义的空间;程序不会出错,也不会对当前程序有什么损坏,从而掩盖你的错误。第三种:指向了一个可用的空间,而且这个空间在程序中正在被使用,野指针的解引用就会刚好修改这个变量x的值,导致这个变量被改变,程序出现离奇错误,从而导致程序奔溃。
(5)指针变量如果是局部变量,则分配到栈上,本身遵从栈的规律,就决定了栈的使用多少会影响这个默认值。因为野指针的值是有一定规律的是不完全随机,但这个值对于我们没有任何意义。
怎么避免野指针
(1)野指针的错误就是指针定义了以后没有初始化,也没有赋值(总之就是指针没有明确的指向一个可用的内存空间),然后就去解引用
(2)避免方法:在指针的解引用之前,一定确保指针指向一个绝对有用的空间。
(3)常规的做法:1.在定义指针时,同时初始化为NULL。2.在指针解引用之前,先判断这个指针是不是NULL。3.在指针结束之后赋值绑定为有效空间
NULL到底是什么?
(1)NULL在C/C++中定义为:

#ifdef	_cplusplus		//定义这个符号就表示当前是C++环境
#define NULL 0			//在C++中NULL
#else
#define NULL (void *)0	//在C中NULL是强制类型转换为void * 的0,可以适用于任何
#endif

(2)在C语言中,int *p;你可以p = (int *)0;但是不可以p = 0;因为类型不同
(3)所以NULL的实质就是0,然后我们给指针赋初值为NULL,其实就是让指针指向0地址处。为什么指向0地址?2个原因。第一层原因是0地址处作为一个特殊地址(我们认为指针指向这里就表示指针没有初始化,就是野指针);第二层意思是:这个地址0地址在一般的操作系统中都是不可访问的,如不按规矩写代码直接去解引用就会触发段错误。
(4)一般在判断指针是否是野指针时,都写成 if(null != p) 而不是写成 if(p != null) ;原因是:如果NULL写在后面,当中间是==号的时候,有时候容易忘记写成了=,这时候其实程序已经错误,但是编译器不会报错,对于新手来说很难检查出来程序错误。

const关键字与指针

const修饰指针的4种形式
(1)const关键字,在C语言中用来修饰变量,表示这个变量是常量
(2)const修饰指针有4种形式,区分清除这4中即可全部理解const和指针

const int *p;			//p本身不是const的,而p指向的变量是const的
int const *p;			//p本身不是const的,而p指向的变量是const的
int * const p;			//p本身是const的,p指向的变量不是const
const int * const p;	//p本身是const的,p指向的变量也是const

(3)关于指针变量的理解,主要涉及到2个变量:第一个是指针变量p本身,第二个是p指向的那个变量(*p),一个const关键字只能修饰一个变量,所以弄清楚这4个表达式的关键就是搞清楚const放在某个位置是修饰谁的
const变量修饰的变量是不能改的?

const int a = 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值