当前位置: 首页 > news >正文

[c/c++] const

const 和 #define 的区别 ?

const 和指针一块出现的时候,到底谁不能修改 ?

const 和 volatile 能同时修饰一个变量吗 ?

const 在 c++ 中的作用 ?

1 const 和 #define 的区别

const 和 #define 的相同点:

(1) 常数

const 和 #define 定义的对象,我们都可以当做一个常数来使用。


 

const 和 #define 的区别:

(1) 生命周期

#define 在编译预处理的时候会做字符串替换,替换之后宏就不存在了,也就是说宏的声明周期只存在于源码和预处理阶段。在目标文件中,程序运行的时候,宏是不存在的。

const 修饰的变量,在编译阶段会做语法检查,如果有显式修改,会报编译错误。const 常量在运行时也是实际存在的,存在于栈或者数据段中。

(2) 作用域

#define 定义的宏,只要包含了这个头文件,都可以使用这个宏;在源文件中,宏定义之后的代码也都可以访问这个宏;即使宏定义函数内部,那么这个宏定义后边的其它函数也是可以使用这个宏的。

const 修饰的局部变量只能在函数内访问,const 修饰的全局变量和普通全局变量的作用域是相同的。

(3) #define 修饰的宏可以 redifine

如下代码,在函数 test2() 内部对HOURS_PER_DAY 进行了重定义。重定义虽然是在函数内部,但是对后边的函数都是生效的。在 test2() 中重定义,在函数 test3() 中也是生效的。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>#define HOURS_PER_DAY 24void test1() {printf("1, hours per day = %d\n", HOURS_PER_DAY);
}void test2() {#undef HOURS_PER_DAT#define HOURS_PER_DAY 20printf("2, hours per day = %d\n", HOURS_PER_DAY);
}void test3() {printf("3, hours per day = %d\n", HOURS_PER_DAY);
}int main() {test1();test2();test3();return 0;
}

在 c++ 编码规范中,推荐使用 const 常量,而不是 #define。

从上边的分析也可以看出来,#define 是可以重定义的,并且 #define 定义的宏没有作用域限制。这就可能给代码带来不安全性。

而对于 const 来说,局部变量的作用域只是函数内;全局 const 变量也不能重新修改。 const  的作用域限制更加严格,所以使用 const 安全性会更高。

2 const 和指针一块出现的时候,到底谁不能修改

const 修饰的是谁,那么谁就不能修改。

int a = 10;

int * const pa1 = &a; // const 修饰的是 int * 类型,是指针,所以 pa1 不能修改,*pa1 可以修改

const int *pa2 = &a; // const 修饰的是 int 类型,所以 pa2 可以修改,*pa2 不能修改

const int * const pa3 = &a; // pa3 和 *pa3 均不能修改

如下是代码和编译结果。

a 是 const 常量,所以不能修改。

p1 中 const 修饰的是 int 常量,所以 *p1 不能修改,p1 可以修改。

p2 中 const 修饰的是指针,所以 p2 不能修改,*p2 可以修改。

p3 const 修饰了指针和 int 值,所以 p3 不能修改,*p3 也不能修改。

3 const 和 volatile 能不能修饰同一个变量

可以。

这两个关键字,从字面意思上是有一些矛盾的。const 是说这个变量是常数,不能修改;volatile 又说这个变量是易变的。

但是两者可以修饰同一个变量,侧重点并不矛盾。const 是提醒编译器,这个变量是常数,不能在代码中显式修改,我们使用它的目的就是这样的,不让在代码中显式修改;volatile 说变量是易变的,告诉编译器,不要做访问优化,每次访问的时候都要到内存中去取值。

在嵌入式开发中,常常用到 volatile 来修饰寄存器变量,寄存器变量不允许软件显式修改,但是硬件可以修改。这个时候就可以使用 const 和 volatile 进行修饰。

4 const 在 c++ 中的作用

(1) 左值引用指向右值

如下代码 ra2 是左值引用,左值引用不能直接指向一个右值。

ra3 是一个 const 左值引用,可以指向一个右值。

从运行结果可以看出来,const 左值引用可以指向右值,右值也是保存在栈里的, ra3 的地址和 a 的地址挨着。

从运行结果可以看出来,const 引用 ra3,通过地址间接修改也是可以修改的。

#include <iostream>
#include <string>int main() {int a = 10;int &ra1 = a;// int &ra2 = 10; // error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’const int &ra3 = 10;std::cout << "a addr = " << &a << ", ra3 addr = " << &ra3 <<std::endl;int *p = (int *)&ra3;std::cout << "ra3 = " << ra3 << std::endl;*p = 100;std::cout << "ra3 = " <<ra3 << std::endl;return 0;
}

(2) 修饰成员函数

用 const 修饰的成员函数,在函数中不能修改类的成员变量。

#include <iostream>
#include <string>class Test {
public:Test() {a = 10;std::cout << "Test()" << std::endl;}~Test() {std::cout << "~Test()" << std::endl;}void Do() const {a = 100;}void Do1(int data) {a = 100;data = 200;}int a;
};int main() {Test t;t.Do();return 0;
}

5 参考

linux 下 c 语言中的局部 const 常量可以修改

 [c 语言] 实例观察 c 语言中 volatile 的作用

相关文章:

[c/c++] const

const 和 #define 的区别 ? const 和指针一块出现的时候&#xff0c;到底谁不能修改 &#xff1f; const 和 volatile 能同时修饰一个变量吗 ? const 在 c 中的作用 ? 1 const 和 #define 的区别 const 和 #define 的相同点&#xff1a; (1) 常数 const 和 #define 定…...

生成商品条码

php生成商品条码&#xff0c;编码格式为&#xff1a;EAN13 下载第三方包&#xff1a;composer require codeitnowin/barcode 生成条码代码&#xff1a; $filename \Str::random(40) . .png;$barcode new BarcodeGenerator();$barcode->setText($barCode);$barcode->s…...

langchain学习笔记(十一)

关于langchain中的memory&#xff0c;即对话历史&#xff08;message history&#xff09; 1、 Add message history (memory) | &#x1f99c;️&#x1f517; Langchain RunnableWithMessageHistory&#xff0c;可用于任何的chain中添加对话历史&#xff0c;将以下之一作为…...

LabVIEW高温摩擦磨损测试系统

LabVIEW高温摩擦磨损测试系统 介绍了一个基于LabVIEW的高温摩擦磨损测试系统的软件开发项目。该系统实现高温条件下材料摩擦磨损特性的自动化测试&#xff0c;通过精确控制和数据采集&#xff0c;为材料性能研究提供重要数据支持。 项目背景 随着材料科学的发展&#xff0c;…...

基于YOLOv5的驾驶员疲劳驾驶行为​​​​​​​检测系统

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文主要内容:详细介绍了疲劳驾驶行为检测整个过程&#xff0c;从数据集到训练模型到结果可视化分析。 博主简介 AI小怪兽&#xff0c;YOLO骨灰级玩家&#xff0c;1&#xff09;YOLOv5、v7、v8优化创新&#xff0c;轻松涨点和模型轻量…...

融合软硬件串流多媒体技术的远程控制方案

远程技术已经发展得有相当水平了&#xff0c;在远程办公&#xff0c;云游戏&#xff0c;云渲染等领域有相当多的应用场景&#xff0c;以向日葵&#xff0c;todesk rustdesk等优秀产品攻城略地&#xff0c;估值越来越高。占据了通用应用的方方面面。 但是细分市场&#xff0c;还…...

Spring中的数据校验---JSR303

介绍–什么是JSR303 JSR 303是Java中的一项规范&#xff0c;用于定义在Java应用程序中执行数据校验的元数据模型和API。JSR 303的官方名称是"Bean Validation"&#xff0c;它提供了一种在Java对象级别上执行验证的方式&#xff0c;通常用于确保输入数据的完整性和准…...

“揭秘网络握手与挥别:TCP三次握手和四次挥手全解析“

前言 在计算机网络中&#xff0c;TCP&#xff08;传输控制协议&#xff09;是一种重要的通信协议&#xff0c;用于在网络中的两台计算机之间建立可靠的连接并交换数据。TCP协议通过“三次握手”和“四次挥手”的过程来建立和终止连接&#xff0c;确保数据的准确传输。 一、三…...

Java开发工程师面试题(Spring)

一、Spring Bean的生命周期 生命周期可以分为以下几步&#xff1a; 通过Spring框架的beanFactory工厂利用反射机制创建bean对象。根据set方法或者有参构造方法给bean对象的属性进行依赖注入。判断当前bean对象是否实现相关aware接口&#xff0c;诸如beanNameAware、beanFactor…...

【C++】string类的基础操作

&#x1f497;个人主页&#x1f497; ⭐个人专栏——C学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读 1. 基本概述 2. string类对象的常见构造 3. string类对象的容量操作 4. string类对象的访问及遍历操作 5. 迭代器 6.…...

Java项目:40 springboot月度员工绩效考核管理系统009

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本系统的功能分为管理员和员工两个角色 管理员的功能有&#xff1a; &#xff08;1&#xff09;个人中心管理功能&#xff0c;添加管理员账号…...

opengl 学习(三)-----着色器

着色器 分类demo效果解析教程 分类 OPengl C demo #include "glad/glad.h" #include "glfw3.h" #include <iostream> #include <cmath> #include <vector>#include <string> #include <fstream> #include <sstream>…...

电销平台架构的演变与升级

简介 信也科技电销平台承载了公司400多坐席的日常外呼任务&#xff0c;随着公司业务规模不断增长&#xff0c;业务复杂度不断提升&#xff0c;营销模式需要多样化&#xff0c;营销流程需要更加灵活。为了更好地赋能业务、提高客户转化率&#xff0c;电销平台不断升级优化&#…...

轻薄蓝牙工牌室内人员定位应用

在现代化企业管理的背景下&#xff0c;轻薄蓝牙工牌人员定位应用逐渐崭露头角&#xff0c;成为提升企业效率和安全性的重要工具。本文将从轻薄蓝牙工牌的定义、特点、应用场景以及未来发展趋势等方面&#xff0c;对其进行全面深入的探讨。 一、轻薄蓝牙工牌的定义与特点 轻薄…...

好物周刊#46:在线工具箱

https://github.com/cunyu1943 村雨遥的好物周刊&#xff0c;记录每周看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;每周五发布。 一、项目 1. twelvet 一款基于 Spring Cloud Alibaba 的权限管理系统&#xff0c;集成市面上流行库&#xff0c;可以作用为快…...

20240306-1-大数据的几个面试题目

面试题目 1. 相同URL 题目: 给定a、b两个文件&#xff0c;各存放50亿个url&#xff0c;每个url各占64字节&#xff0c;内存限制是4G&#xff0c;让你找出a、b文件共同的url&#xff1f; 方案1&#xff1a;估计每个文件的大小为50G64320G&#xff0c;远远大于内存限制的4G。所以…...

Vue中如何处理用户权限?

在前端开发中&#xff0c;处理用户权限是非常重要的一个方面。Vue作为一种流行的前端框架&#xff0c;提供了很多便捷的方式来管理用户权限。本文将介绍一些Vue中处理用户权限的方法 1. 使用路由守卫 Vue Router提供了一个功能强大的功能&#xff0c;即导航守卫&#xff08;N…...

【STM32】HAL库 CubeMX教程---基本定时器 定时

目录 一、基本定时器的作用 二、常用型号的TIM时钟频率 三、CubeMX配置 四、编写执行代码 实验目标&#xff1a; 通过CUbeMXHAL&#xff0c;配置TIM6&#xff0c;1s中断一次&#xff0c;闪烁LED。 一、基本定时器的作用 基本定时器&#xff0c;主要用于实现定时和计数功能…...

2024年最新整理腾讯云学生服务器价格、续费和购买流程

2024年腾讯云学生服务器优惠活动「云校园」&#xff0c;学生服务器优惠价格&#xff1a;轻量应用服务器2核2G学生价30元3个月、58元6个月、112元一年&#xff0c;轻量应用服务器4核8G配置191.1元3个月、352.8元6个月、646.8元一年&#xff0c;CVM云服务器2核4G配置842.4元一年&…...

【QT】重载的信号槽/槽函数做lambda表达式

重载的信号槽 函数指针&#xff1a; int fun(int a,long b) int (*funp)(int, long) fun; 实现回调函数就需要函数指针 信号重载 派生类槽函数发送两个信号 派生类给父类发两个信号 void (SubWidget::*mysigsub)() &SubWidget::sigSub;connect(&subw,mysigsub,t…...

小波分解选型指南:如何为你的数据选择最合适的pywt小波函数(db4/haar/symlets对比)

小波分解选型指南&#xff1a;如何为你的数据选择最合适的pywt小波函数&#xff08;db4/haar/symlets对比&#xff09; 在信号处理领域&#xff0c;小波分解就像一把瑞士军刀&#xff0c;能够同时提供时域和频域的信息。但面对pywt库中琳琅满目的小波函数——从经典的Haar到复杂…...

RevokeMsgPatcher:突破微信消息限制的高效管理工具

RevokeMsgPatcher&#xff1a;突破微信消息限制的高效管理工具 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁&#xff08;我已经看到了&#xff0c;撤回也没用了&#xff09; 项目地址: https://gitcode.com/G…...

CAN总线波特率计算器工具开发指南(Python+PyQt5)

CAN总线波特率计算器工具开发指南&#xff08;PythonPyQt5&#xff09; 在汽车电子工程领域&#xff0c;CAN总线作为车载网络的骨干&#xff0c;其通信质量直接影响整车系统的稳定性。而波特率作为CAN通信的基础参数&#xff0c;其配置精度直接决定了总线能否正常工作。传统的手…...

实战复盘:我是如何用Turbo Intruder的race.py脚本,5分钟挖到一个高并发订单漏洞的

高并发漏洞狩猎实录&#xff1a;从Turbo Intruder脚本调优到电商系统攻防实战 去年在一次众测项目中&#xff0c;我偶然发现某电商平台的积分兑换系统存在并发处理缺陷。这个漏洞最终被评级为高危&#xff0c;而整个挖掘过程只用了不到5分钟——关键就在于对Turbo Intruder的ra…...

DevExpress GridControl动态添加行的两种高效实现方式

1. 两种动态添加行的核心方法对比 刚接触DevExpress GridControl时&#xff0c;最让我头疼的就是动态添加行这个基础操作。网上教程要么太零散&#xff0c;要么直接贴代码不解释原理。经过多个项目实战&#xff0c;我总结出最高效的两种实现方式&#xff0c;就像给表格数据&quo…...

OpenClaw浏览器自动化:nanobot镜像实现定时抢购与价格监控

OpenClaw浏览器自动化&#xff1a;nanobot镜像实现定时抢购与价格监控 1. 为什么选择OpenClaw实现浏览器自动化 去年双十一期间&#xff0c;我为了抢购某款显卡&#xff0c;连续三天凌晨守着电脑刷新页面&#xff0c;结果还是错过了补货。这种经历让我开始寻找自动化解决方案…...

以太网MAC与PHY接口技术详解

以太网PHY、MAC及其通信接口技术解析1. 以太网接口架构概述1.1 基本组成结构以太网接口电路从硬件角度可分为两大核心组件&#xff1a;MAC控制器&#xff08;Media Access Control&#xff09;&#xff1a;负责数据链路层的媒体访问控制PHY芯片&#xff08;Physical Layer&…...

ApiPost实战指南:从接口创建到自动化测试的全流程解析

1. 从零开始创建你的第一个API接口 作为一个常年和API打交道的开发者&#xff0c;我深知新手第一次接触接口工具时的迷茫。ApiPost作为一款国产的API开发工具&#xff0c;用起来确实比Postman更顺手&#xff0c;特别是对中文用户特别友好。下面我就带你一步步创建第一个接口&am…...

ai辅助stm32开发,向快马描述需求即可获得精准的f103c8t6引脚配置代码

最近在做一个基于STM32F103C8T6的小项目&#xff0c;需要用到UART、I2C、PWM、ADC和GPIO等多种外设。作为嵌入式开发新手&#xff0c;最头疼的就是引脚分配和初始化代码的编写。好在发现了InsCode(快马)平台的AI辅助开发功能&#xff0c;用自然语言描述需求就能得到专业的代码解…...

嵌入式pRNG:基于WDT与LFSR的轻量级硬件熵随机数生成器

1. pRNG库概述&#xff1a;面向嵌入式系统的轻量级熵收集型伪随机数生成器pRNG&#xff08;Pseudo-Random Number Generator&#xff09;是一个专为资源受限微控制器设计的开源伪随机数生成库&#xff0c;其核心设计哲学是在极小内存开销下&#xff0c;通过硬件时序抖动提取物理…...