[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 和指针一块出现的时候,到底谁不能修改 ? const 和 volatile 能同时修饰一个变量吗 ? const 在 c 中的作用 ? 1 const 和 #define 的区别 const 和 #define 的相同点: (1) 常数 const 和 #define 定…...

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

langchain学习笔记(十一)
关于langchain中的memory,即对话历史(message history) 1、 Add message history (memory) | 🦜️🔗 Langchain RunnableWithMessageHistory,可用于任何的chain中添加对话历史,将以下之一作为…...

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

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

融合软硬件串流多媒体技术的远程控制方案
远程技术已经发展得有相当水平了,在远程办公,云游戏,云渲染等领域有相当多的应用场景,以向日葵,todesk rustdesk等优秀产品攻城略地,估值越来越高。占据了通用应用的方方面面。 但是细分市场,还…...

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

“揭秘网络握手与挥别:TCP三次握手和四次挥手全解析“
前言 在计算机网络中,TCP(传输控制协议)是一种重要的通信协议,用于在网络中的两台计算机之间建立可靠的连接并交换数据。TCP协议通过“三次握手”和“四次挥手”的过程来建立和终止连接,确保数据的准确传输。 一、三…...
Java开发工程师面试题(Spring)
一、Spring Bean的生命周期 生命周期可以分为以下几步: 通过Spring框架的beanFactory工厂利用反射机制创建bean对象。根据set方法或者有参构造方法给bean对象的属性进行依赖注入。判断当前bean对象是否实现相关aware接口,诸如beanNameAware、beanFactor…...

【C++】string类的基础操作
💗个人主页💗 ⭐个人专栏——C学习⭐ 💫点击关注🤩一起学习C语言💯💫 目录 导读 1. 基本概述 2. string类对象的常见构造 3. string类对象的容量操作 4. string类对象的访问及遍历操作 5. 迭代器 6.…...

Java项目:40 springboot月度员工绩效考核管理系统009
作者主页:源码空间codegym 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本系统的功能分为管理员和员工两个角色 管理员的功能有: (1)个人中心管理功能,添加管理员账号…...

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多坐席的日常外呼任务,随着公司业务规模不断增长,业务复杂度不断提升,营销模式需要多样化,营销流程需要更加灵活。为了更好地赋能业务、提高客户转化率,电销平台不断升级优化&#…...

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

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

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

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

【STM32】HAL库 CubeMX教程---基本定时器 定时
目录 一、基本定时器的作用 二、常用型号的TIM时钟频率 三、CubeMX配置 四、编写执行代码 实验目标: 通过CUbeMXHAL,配置TIM6,1s中断一次,闪烁LED。 一、基本定时器的作用 基本定时器,主要用于实现定时和计数功能…...

2024年最新整理腾讯云学生服务器价格、续费和购买流程
2024年腾讯云学生服务器优惠活动「云校园」,学生服务器优惠价格:轻量应用服务器2核2G学生价30元3个月、58元6个月、112元一年,轻量应用服务器4核8G配置191.1元3个月、352.8元6个月、646.8元一年,CVM云服务器2核4G配置842.4元一年&…...

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

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...