const和指针不得不说的事

可以说,指针是写代码的人无可避免的一个坎,而指针遇上const则有各种难解难分的关系,下面将其一层一层拆开。

1 两种交互类型

指针和const限定符之间,不外乎两种交互类型:

  • 指向const对象的指针
  • const指针

2 可能的组合

在详细描述这两种类型前,先给出一些可能的组合方式:

char *p

const char *p

char const *p

char *const p

const char **p

char const **p

char *const *p

char **const p

看到这里,我已经晕了,下面逐一进行拆解。

3 指向const对象的指针

顾名思义,指针指向的对象是const类型,不允许用指针来修改所指const对象的值。

定义:const int *p

p是一个指向char类型const对象的指针,const限定了p所指的对象,而非p本身,p不是const,定义时不必初始化,且允许对p重新赋值,使其指向另一对象(const对象或非const对象):

	int num = 100;
	const val = 200;
	const int *p = # //ok
	p = &val; //ok

3.1 允许将非const对象的地址赋给指向const对象的指针,但任何试图使用指向const对象的指针去修改所指对象的值,都是不允许的,尽管其所指对象可能是非const的

	int num = 100;
	const int *p = # //ok
	*p = 150; //error

3.2不允许使用void*指针保存const对象的地址,必须使用const void*类型指针来保存const对象地址:

	const int val = 200;
	const void *p = &val; //ok
	void *pv = &val; //error

3.3 不允许将const对象的地址赋给普通的、非const对象的指针:

	const int val = 200;
	int *p = &val; //error
	const int *pv = &val; //ok

4 const指针

定义:int *const p = &val //假设val已经定义

顾名思义,指针p本身是const的,定义时必须初始化,且定以后不能再修改:

	int val = 200;
	int num = 100;
	int *const p = &val; //ok
	p = # //error
	p = p; // error, 即使赋回同样的值也不允许

指针本身是const,与其所指对象能否被修改并无关系,这完全取决于所指对象的类型:

	int val = 200;
	const int num = 100;
	int *const p = &val; //ok
	*p = 250; //ok, val is not const
	const int *const pv = # //ok
	*pv = 150; //error, num is const

5 指向const对象的const指针

定义:const int val = 100;const int *const p = &val

既不能修改指针p指向的对象,也不能修改p的指向
6 指针和typedef

	typedef int* pint;
	const pint p; //ok,尽管没有初始化,编译时却通过了
	int val = 100;
	p = &val;//error,p是const指针

p的真正类型是:int *const p

事实上,int const val与const int val是一样的,于是pint const p能更好理解。其实,const pint p应该这样理解,p是pint类型的const变量,而pint是个指针,所以p是个指针,p又是const变量,因此p是个const类型的指针:int *const p
7 现在开始处理让人眼花的各种组合

首先明确一点,const int val与int const val是等价的,有一个诀窍是,将类型关键字去掉,看const修饰的是什么,如去掉int后,剩下const val,表明val是const的

然后看const修饰指针的情况,有一个关键点是看const是在*前面还是后面。

const char *p,去掉类型关键字,const *p,const修饰*p,修饰的是p所指的内容,因此p是个指向const对象的非const指针

char const *p,去掉类型关键字,const *p,与const char *p是等价的,就跟const int val与int const val是等价的一样

char *const p,去掉类型关键字,*const p,const 修饰p,修饰的是指针p本身,因此p是个指向char类型的const指针

char const **p,涉及两个指针,p和*p,将*p看做一个整体,用A来代替,char const *A,这就很好理解了,*p是一个指向char类型const对象的普通指针,看一个实验:

	int val = 100;
	int num = 200;
	int  *p = &val;
	int *pn = #
	const int **pp;
	pp = &p; //ok,pp可以重新赋值,表明pp不是const,这里编译器给出一个warning,如果p改成int const *p = &val则没有warning
	*pp = pn; //ok,可以通过pp修改所指对象的值,表明pp所指对象不是const
	**pp = 150; //error,不能通过*pp修改*pp所指对象的值,表明*pp是指向const对象的指针

const char **p与char const **p是一样的

char **const p,涉及两个指针,p和*p,const修饰p,因此p是const的,至于*p的特性,看下面一个例子会比较清楚

	int val = 100;
	int num = 200;
	int  *p = &val;
	int *pn = #
	int **const pp;
	pp = &p; //error,pp是const,不允许重新赋值,但是上面一句定义时没初始化却没报错
	*pp = pn; //ok,*pp可以重新赋值,说明指针*pp非const,也说明pp不是指向const对象
	**pp = 150; //ok,可以通过指针*pp修改所指对象的值,说明*pp不是指向const对象的

char *const *p,虽然有两个星号,看起来似乎很玄奥,其实与char const *p是一样的道理,前者是指向char*类型const对象的指针,后者是指向char类型const对象的指针,看下面例子:

	int val = 100;
	int num = 200;
	int  *p = &val;
	int *pn = #
	int *const *pp;
	pp = &p; //ok,pp指向int*类型const对象,可以重新赋值
	*pp = pn; //error,不允许通过pp来修改其所指对象的值








 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值