const和指针的结合

本文详细介绍了const关键字与指针的结合使用,包括const修饰一级指针的三种方式及其含义。第一种方式使得指针不可修改所指变量的值,第二种方式使指针自身不可改变指向,第三种方式同时限制两者。对于二级指针,const修饰二级指针的**部分,意味着不能通过二级指针修改一级指针的指向,以防止修改常量的地址。文章通过实例代码解析了const与指针结合的规则,并指出其在实际编程中的应用和限制。

const和指针的结合

在定义一个const指针常量的时候,不同位置的const产生的结果也是不同的。

首先我们需要知道,一个普通的指针是不能指向一个常量的地址的:

#include <stdio.h>

int main()
{
	const int a  = 10;
	int* p = &a;
}

上面的代码编译时无法通过的,这是因为a是一个常量,而如果我们把a的地址泄露给了一个普通的指针p,就相当于我们可以通过*p来间接修改a内存的值,这就有违背使用常量的初衷。但我们用一个常指针指向一个普通的变量是允许的。

要定义一个可以指向常量地址的指针,就需要用到const和指针的结合。

const和一级指针结合

const和一级指针的结合有三种方式:

  1. const int *p;int const *p;(这两条代码的效果是一致的)
  2. int * const p;
  3. const int * const p;int const * const p;

第一种方式的const修饰的是*p,就相当于我们无法再通过 *p来修改 p指向变量的值了,如在上面的代码中,我们要定义指向常量的指针,就可以用这种方式定义。
第二种方式的const修饰的是p,相当于我们无法再改变p的指向,如面向对象编程中的this指针。
第三种方式就是第一种方式和第二种方式的结合。

#include <iostream>
#include <typeinfo>
using namespace std;

int main()
{
	int a;
	const int* p1 = &a;
	int* const p2 = &a;
	const int* const p3 = &a;

	cout << typeid(p1).name() << endl;
	cout << typeid(p2).name() << endl;
	cout << typeid(p3).name() << endl;
}

在这里插入图片描述
上面程序的运行结果中,我们可以看到,第二种方式定义的指针,const和指针的类型是没有关系的,因此,第二种方式定义的指针赋值给一个普通的指针肯定也是可以的。
通过上面的分析我们可以知道:

  • const int a = 10; int *p = &a;int a; const int* p1 = &a; int* p2 = p1;用一个普通的指针指向一个const修饰的量是不允许的
  • int a; const int *p = &a;用一个const指针指向一个普通的变量是可以的
  • int a; int* const p1 = &a; int *p2 = p1;是允许的

const和二级指针结合

#include <iostream>
#include <typeinfo>
using namespace std;

int main()
{
	int a = 10;
	int* p1 = &a;
	const int** p2 = &p1;
}

上面的代码能不能编译通过呢?按照我们之前对一级指针的分析, int* p1; const int *p2 = p1;是允许的,那const int** p2 = &p1;是不是也可以呢?
答案是不行的:
在这里插入图片描述
这里解释以下错误的原因:
二级指针p2涉及三个表达式:p2、*p2、**p2
const修饰的是 **p2,**p2的值不能修改,但是 *p2的值是可以修改的。

#include <iostream>
#include <typeinfo>
using namespace std;

int main()
{
	int a = 10;
	int* p1 = &a;
	const int** p2 = &p1;
	const int b = 20;
	*p2 = &b;
}

分析上面的代码,假设可以编译通过,如果我们把 *p2指向一个常量的地址,那么就可以通过 *p1 修改 常量b的值,也就是把一个常量的地址泄露给了一个普通的指针,这是不允许的。

要使编译可以通过,我们可以这样修改,把p1声明为const int* p1 = &a;,这样我们就不能通过 *p1修改值了;或者把p2声明为const int* const * p2 = &p1;这样 *p2就不能被修改,就不会发生上面的错误了。

#include <iostream>
#include <typeinfo>
using namespace std;

int main()
{
	int a = 10;
	const int* p1 = &a;
	const int** p2 = &p1;
}
#include <iostream>
#include <typeinfo>
using namespace std;

int main()
{
	int a = 10;
	int* p1 = &a;
	const int* const * p2 = &p1;
}

其他const和二级指针结合的情况可以用和一级指针结合的情况来分析,这里就不再赘述。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_200_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值