C++ const与指针

news2025/4/17 13:46:26

const与指针

1.const在C语言和C++中的区别

(1)在C语言中
#include<stdio.h>
int main()
{
	const int n = 10;  
	int arr[n] = { 1,2 }; //error
	return 0;
}

在这里插入图片描述在C语言中,const修饰的变量是只读变量(常变量),const限制了其“写”操作,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。const修饰的变量是不能作左值,也不能用来定义数组长度,和用在switch语句中,可以取地址。
所以以上代码中,在C语言中这样定义数组是错误的,因为在C语言中认为n就是一个变量,虽然加了const修饰,但它仍然是变量,只不过const限制了其“写”操作,而在C语言中规定,定义数组时数组大小是一个大于零的整形常量。

C编译

#include<stdio.h>
int main()
{
	const int a = 10;
	int b = 0;
	int* p = (int*)&a;
	*p = 100;
	b = a;// C编译时,会借助一个“临时空间”,先将a的值取出来存放在临时空间,在将临时空间的值赋给b
	printf("a=%d b=%d *p=%d", a, b, *p);
	return 0;
}

按照C的编译方法,虽然a用const修饰,但是可以通过p去改变a的值,将a的值10通过p去修改为100;在对内存进行访问,将a的值100(通过p去修改,此时为100)赋值给b,在C编译时,会借助一个“临时空间”,先将a的值取出来存放在临时空间,在将临时空间的值赋给b,b的值也是100,所以按照C的编译方式,输出的结果为:
在这里插入图片描述

(2)在C++中
#include<iostream>
using namespace std;
int main()
{
	const int n = 10;
	int ar[n] = { 1,2,3,4 }
	return 0;
}

在C++中,使用const修饰变量时,是以常性为主,遇见常变量会用值去替换掉。被const修饰的变量是常量,必须初始化,可以在定义数组长度时使用,也可以在switch语句中使用。
在C++中这样定义数组是合法的,会用整数值10去替换n,等价于:int ar[10] = { 1,2 ,3,4};

C++编译

#include<iostream>
using namespace std;
int main()
{
	const int a = 10;
	int b = 0;
	int* p = (int*)&a;
	*p = 100; // 将 *p的值改为100
	b = a; //C++编译时,直接将a的值替换成10,然后再将10赋值给b
	cout << "a=" << a << " b=" << b << " *p=" << *p << endl;
}

C++编译时,遇见const修饰的变量时(直接使用常变量这个值得时候),会先将其替换成具体的数值,所以使用C++的方式编译,输出的结果为:
在这里插入图片描述

2.const与指针的关系

(1)常变量与指针

对于一个普通变量a,以下代码,在C编译和C++编译中都可以成功编译。

#include<stdio.h>
int main()
{
	int a = 10;
	int* p1 = &a;// p1是一个普通指针
	const int* p2 = &a;// 指向为常性(解引用为常性)const修饰的是“*”
	int const* p3 = &a;// 等价于const int* p2 = &a
	int* const p4 = &a;// 指针变量自身为常性(const修饰的是指针p3)
	const int* const p5 = &a;// 指向(解引用)和指针变量自身都为常性
	return 0;
}
#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	int* p1 = &a;
	const int* p2 = &a;
	int const* p3 = &a;
	int* const p4 = &a;
	const int* const p5 = &a;
	return 0;

}

对于一个const修饰的变量a,编译方式不同,结果不同
C编译时可以成功编译:

#include<stdio.h>
int main()
{
	const int a = 10;
	int* p1 = &a;  
	const int* p2 = &a;  
	int* const p3 = &a; 
	const int* const p4 = &a;  
	int* p5 = (int*)&a;  
	return 0;
}

C++编译时不合法:

#include<iostream>
using namespace std;
int main()
{
	const int a = 10;
	int* p1 = &a;  // error  编译不通过,因为可以使用普通指针p1解引用去改变a的值,能力扩大
	const int* p2 = &a;  // ok  const修饰指向(*),所以不能通过p2解引用去修改a的值,但是指针p2本身可以修改
	int* const p3 = &a;  // error  const修饰指针p3,不允许修改p3,但是可以通过对p3解引用修改a的值,能力扩大
	const int* const p4 = &a;  // ok 指针本身和其指向均不能被修改
	int* p5 = (int*)&a;  // 强转,C语言中的“强盗”,虽然编译可以通过,但是不安全
	return 0;
}

在这里插入图片描述

(2)同类型指针的赋值兼容规程

以下代码在C编译和C++编译下都可以成功编译:

int main()
{
	int a = 10, b = 20;
	int* p = &a;  // 定义一个普通指针p指向a的地址
	int* s1 = p;  // ok 定义一个普通指针s1指向p指向的地址,也就是s1和p都指向a的地址
	const int* s2 = p;  // ok const修饰指向,能力缩小
	int* const s3 = p;  // ok 指针s3为常性,但可以通过解引用修改a的值(允许)
	const int* const s4 = p;  // ok
	return 0;
}

以下代码在C编译下可以通过,在C++编译下不合法:

int main()
{
	int a = 10, b = 20;
	const int* p = &a;  // const修饰指向,不能通过对p解引用去修改a的值,但是可以修改指针p本身
	int* s1 = p;  // error  能力扩张,
	const int* s2 = p;  // ok  const修饰指向,即不能通过s2去修改a的值(s2和p都指向a),但是s2本身可以修改,s2的修改不影响p
	int* const s3 = p;  // error  const修饰指针s3,即可以通过对s3解引用去修改a的值(不允许),但s3本身不允许被修改
	const int* const s4 = p;  // ok
}

在这里插入图片描述
以下代码在C编译和C++编译下都可以成功编译:

int main()
{
	int a = 10, b = 20;
	int* const p = &a;  // const修饰指针p,即p本身不允许被修改,但是其指向可以被修改
	int* s1 = p;  // ok  定义一个指针s1指向a(和p都指向a),可以通过对s1解引用去修改a的值,也可以对s1本身进行修改,不会影响p
	const int* s2 = p;  // ok  const修饰指向,即不允许通过对s2解引用修改a的值,但是s2可以被修改,不影响p
	int* const s3 = p;  // ok  const修饰s3,即不允许修改s3本身,但是可以通过对s3解引用去修改a的值
	const int* const s4 = p;  // ok
}

总结:
1.能力强的指针赋值给能力收缩的指针(能力收缩,允许)
2.能力弱的指针不能赋值给扩张的指针(能力扩张,不允许)
3.编译方式的不同,会导致不同的结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/792776.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

假如三国有网络安全攻防演练

东汉末年&#xff0c;天下三分&#xff0c;而奠定这一局势的战役就是历史上赫赫有名的“赤壁大战”。 作为我国以少胜多的经典战例&#xff0c;赤壁之战汇聚了三国最顶级的名臣武将&#xff0c;期间各种计谋、策略环环相扣&#xff0c;高潮迭起&#xff0c;攻守双方你方唱罢我…

【Java|golang】860. 柠檬水找零

在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品&#xff0c;&#xff08;按账单 bills 支付的顺序&#xff09;一次购买一杯。 每位顾客只买一杯柠檬水&#xff0c;然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零&#xff0c;…

AtcoderABC235场

A - Rotate A - Rotate 题目大意 题目要求给定一个3位的整数abc&#xff0c;其中每个数字都不是0。计算abc bca cab的结果。 思路分析 将a、b和c按照题目要求的顺序连接起来&#xff0c;得到字符串abc、bca和cab。将这三个字符串转换为整数&#xff0c;分别表示为变量abc…

【后端面经】微服务构架 (1-3) | 熔断:抖抖抖不停?微服务熔断策略让你的系统稳如泰山!

文章目录 一、前置知识1、什么是熔断?2、什么是限流?3、什么是降级?4、怎么判断微服务出现了问题?A、指标有哪些?B、阈值如何选择?C、超过阈值之后,要不要持续一段时间才触发熔断?5、服务恢复正常二、面试环节1、面试准备2、面试基本思路三、总结 在微服务构架中…

ModuleNotFoundError: No module named ‘transformers.models.mmbt‘

使用simpletransformers时出现ModuleNotFoundError: No module named transformers.models.mmbt’错误。 1. 报错代码&#xff1a; from simpletransformers.classification import ClassificationModel 2. 报错结果 3. 报错原因 transformers和simpletransformers版本的问…

【C语言进阶篇】数组指针都学过了那么函数指针你了解嘛?

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言&#x1f4ac; 函数指针&#x1f4ad; 函数名 和 &函数&#x1f4ad; 函数指针的定义&am…

蕨型叶分形

目录 要点 基本语句 EraseMode 习题 1 设置颜色 2 旋转蕨型叶图 3 枝干 4 塞平斯基三角形 要点 蕨型叶是通过一个点的反复变换产生的&#xff0c;假设x是一个含有两个分量的向量&#xff0c;可以用来表示平面内的一个点&#xff0c;则可以用Axb的形式对其进行变换。 基本…

衡器关于检定分度值e和实际分度值d的一点认识

在看衡器认证的文档时有两个概念很容易混淆d(actual scale interval)和e(verification scale interval)&#xff0c;国内文档上翻译为实际分度值和检定分度值。 实际分度值(d)就是称能显示的最小刻度或最小能显示的值跨度&#xff0c;可以理解为可读精度&#xff0c;例如电子秤…

[虚幻引擎] UE里面监控每帧循环里面 C++ 函数的性能, 函数耗时,函数效率,函数执行时间

在使用C开发UE引擎&#xff0c;有时候需要监控函数的执行的执行效率&#xff0c;这个时候有两种方式可以使用。 1. 执行代码耗时时间 double ThisTime 0;{SCOPE_SECONDS_COUNTER(ThisTime);// ...// 一串代码// ...}UE_LOG(LogTemp, Log, TEXT("Stats::Broadcast %.2f&qu…

【Spring Boot】Web开发 — 数据验证

Web开发 — 数据验证 对于应用系统而言&#xff0c;任何客户端传入的数据都不是绝对安全有效的&#xff0c;这就要求我们在服务端接收到数据时也对数据的有效性进行验证&#xff0c;以确保传入的数据安全正确。接下来介绍Spring Boot是如何实现数据验证的。 1.Hibernate Vali…

mysql(三)用户权限管理

目录 前言 一、概述 二、用户权限类型 三、用户赋权 四、权限删除 五、删除用户 前言 为什么要设置用户权限&#xff1f; MySQL设置用户管理权限的主要目的是为了确保数据库的安全性和数据的机密性。以下是一些原因&#xff1a; 1. 安全性&#xff1a;MySQL是一个开源的关系型…

多线程案例 | 单例模式、阻塞队列、定时器、线程池

多线程案例 1、案例一&#xff1a;线程安全的单例模式 单例模式 单例模式是设计模式的一种 什么是设计模式&#xff1f; 设计模式好比象棋中的 “棋谱”&#xff0c;红方当头炮&#xff0c;黑方马来跳&#xff0c;针对红方的一些走法&#xff0c;黑方应招的时候有一些固定的…

【C++初阶】:模板进阶

模板进阶 一.非类型模板参数二.模板的特化1.概念2.函数模板特化3.类的特化1.全特化2.偏特化 三.模板的分离编译 一.非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类…

Play 资产分发(Play Asset Delivery)

一、前言 Google Play发布应用&#xff0c;只支持上传aab格式文件。在之前&#xff0c;Google Play对上传apk文件限制大小不超过150MB&#xff0c;对于新的aab格式文件&#xff0c;也要求生成的目标apk不超过150MB&#xff08;GooglePlay后台使用bundletool生成apk文件&#xf…

虚拟机网络桥接,详细操作步骤,本地连接虚拟机

虚拟机网络桥接 文章目录 虚拟机网络桥接一&#xff0c;首先查看主机连接网络的网关二、打开虚拟机的worksation服务三、修改主机的VMnet8的IPV4属性四、修改虚拟机的workstation的虚拟网络五、修改VMnet8的IP,网关六、把虚拟机设置为桥接模式七、修改虚拟机的静态ip和对应的网…

JAVA面试总结-Redis篇章(三)——缓存雪崩

JAVA面试总结-Redis篇章&#xff08;三&#xff09;——缓存雪崩

测试开发之系统篇 - 常用系统命令

目录 前言&#xff1a; 查看占用端口的进程 Linux Windows 杀死进程 Linux Windows 按名称查看进程 命令行管道 后台运行服务 修改文件 Linux Mac 复制目录到远程 实时查看文件内容 查看正在运行的服务 查看服务状态 重启服务 查看内存状况 查看磁盘状况 …

基于MAXENT模型的生物多样性生境模拟与保护优先区甄选、自然保护区布局优化及未来气候变化下评估及论文写作教程

详情点击链接&#xff1a;基于MAXENT模型的生物多样性生境模拟与保护优先区甄选、自然保护区布局优化及未来气候变化下评估中的应用及论文写作 一&#xff1a;生物多样性保护格局与自然保护区格局优化 1.我国生物多样性格局与分布&#xff1b; 2.我国自然保护区格局与分布&…

前端年度工作述职报告优秀

前端年度工作述职报告优秀篇1 尊敬的各位领导、各位同仁&#xff1a; 大家好!按照20__年度我公司就职人员工作评估的安排和要求&#xff0c;我认真剖析、总结了自己的工作情况&#xff0c;现将本人工作开展情况向各位领导、同仁做以汇报&#xff0c;有不妥之处&#xff0c;希…

注册外部的AudioPolicy,监听焦点变化

开始 AudioFocus分发流程 在上面分发流程分析中&#xff0c;最终是在MediaFocusControl中进行处理的&#xff0c;在requestAudioFocus​方法中可以看到在执行焦点栈逻辑时会先执行AudioPolicy相关逻辑&#xff0c; 因此我们试一试可不可以利用这一点&#xff0c;来注册外部的…