[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 的作用

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

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

相关文章

lanqiao:合根植物

题目描述&#xff1a; 代码实现&#xff1a;

私域商业模式创新:消费增值引领企业业绩飙升

大家好&#xff0c;我是吴军&#xff0c;专注于私域商业模式的深度探索。今天&#xff0c;我要分享的是一个极具启发性的客户故事。这家企业&#xff0c;在短短一个月内&#xff0c;业绩飙升至上百万级别&#xff0c;用户活跃度同样瞩目&#xff0c;日均在线用户稳定在八万至十…

华为数通学习笔记(一):数据通信网络基础

华为数通学习笔记 前言&#xff1a;在学习大数据的过程中&#xff0c;我发现很多地方需要用到网络知识点&#xff0c;由于我哥考取了华为数通 HCIE 证书&#xff0c;目前正在一家大公司担任技术负责人&#xff0c;因此借此机会我要向他学习这方面的知识点&#xff0c;希望能够拓…

dbeaver更换下载驱动地址

DBeaver 是一个免费开源的数据库工具&#xff0c;提供对多种数据库系统的支持&#xff0c;包括 MySQL、PostgreSQL、Oracle、SQLite 等。它是一个通用的数据库管理工具&#xff0c;可以帮助用户连接、管理和查询各种类型的数据库。 下载地址 使用dbeaver连接数据库时需要先下…

Linux:kubernetes(k8s)探针LivenessProbe的使用(9)

他做的事情就是当我检测的一个东西他不在规定的时间内存在的话&#xff0c;我就让他重启&#xff0c;这个检测的目标可以是文件或者端口等 我这个是在上一章的基础之上继续操作&#xff0c;我会保留startupProbe探针让后看一下他俩的执行优先的一个效果 Linux&#xff1a;kuber…

洛谷P2233 公交车路线

本题题号特殊&#xff0c;相对简单。 题目描述 在长沙城新建的环城公路上一共有 88 个公交站&#xff0c;分别为 A、B、C、D、E、F、G、H。公共汽车只能够在相邻的两个公交站之间运行&#xff0c;因此你从某一个公交站到另外一个公交站往往要换几次车&#xff0c;例如从公交站…

【C++从0到王者】第五十站:B树

文章目录 一、内查找与外查找1.内查找2.外查找 二、B树概念三、B树的插入1.B树的插入分析2.B树插入总结3.插入代码实现4.B树满树和最空时候的对比5.B树的删除6.遍历B树7.B树的性能分析 一、内查找与外查找 1.内查找 像我们之前所用的在内存中的查找就是内查找 种类数据格式时…

C#,基于密度的噪声应用空间聚类算法(DBSCAN Algorithm)源代码

1 聚类算法 聚类分析或简单聚类基本上是一种无监督的学习方法&#xff0c;它将数据点划分为若干特定的批次或组&#xff0c;使得相同组中的数据点具有相似的属性&#xff0c;而不同组中的数据点在某种意义上具有不同的属性。它包括许多基于差分进化的不同方法。 E、 g.K-均值…

学习经验分享【NO.21】近期中文核心期刊目标检测论文理解

前言&#xff1a;最近比较忙&#xff0c;很久没有翻看知网论文了&#xff0c;看了下yolo改进相关的论文发现基于YOLOv5改进的核心期刊论文还是层出不穷&#xff0c;并没有因为已经是2024年了YOLOv9的出现而导致论文不好发&#xff0c;同时YOLOv8的论文也出了不少&#xff0c;所…

火柴排队(逆序对 + 离散化)

505. 火柴排队 原题链接 思路 如下是画图分析的一些过程 在这里贪心的思路是排序&#xff0c;然后两个数组都是从小到大那样对应的话最终的答案可达到最小 而我们只能交换相邻的火柴&#xff0c;故在这里先假设一个简化版本&#xff0c;即A有序&#xff0c;而只需要对B进行…

Java定时调度

在Java应用程序中&#xff0c;定时调度是一项重要的任务。它允许你安排代码执行的时间&#xff0c;以便在将来的某个时刻自动执行任务。Java提供了多种方式来实现定时调度&#xff0c;其中最常用的是Java的Timer和ScheduledExecutorService。 在本教程中&#xff0c;我们将学习…

990-39产品经理:Top 5 Most Common Incident Response Scenarios 五大最常见的事件响应场景

Top 5 Most Common Incident Response Scenarios 五大最常见的事件响应场景 Dealing with a cyber incident can be a daunting experience. Whether you’re targeted by phishing, malicious network scanning, or ransomware, it’s easy to feel overwhelmed. Even if you…

Frontend - Boostrap 消息弹窗

目录 一、下载 &#xff08;一&#xff09;中文官网 &#xff08;二&#xff09;bootstrap v3 依赖 jQuery 插件 二、解压并安装 &#xff08;一&#xff09;解压 1. 压缩包解压 2. 简化文件 &#xff08;二&#xff09;安装 三、配置 &#xff08;一&#xff09;bas…

Docker 配置阿里云镜像加速器

一、首先需要创建一个阿里云账号 二、登录阿里云账号 三、进入控制台 四、搜索容器镜像服务&#xff0c;并选择 五、选择镜像工具中的镜像加速 六 、配置镜像源 注意&#xff1a;有/etc/docker文件夹的直接从第二个命令开始

网络安全成全国两会热点话题,网络安全你知多少?

2024全国两会正召开的如火如荼&#xff0c;目前已诞生多个热点话题&#xff0c;比如教育、稳就业、促增收等等&#xff0c;其中网络安全也成全国两会热点话题之一。会上&#xff0c;多位全国政协委员、全国人大代表、行业专家、学者、企业大咖纷纷携网络安全相关提案、议案上会…

Sleuth(Micrometer)+ZipKin分布式链路追踪

Sleuth(Micrometer)ZipKin分布式链路追踪 Micrometer springboot3之前还可以用sleuth&#xff0c;springboot3之后就被Micrometer所替代 官网https://github.com/spring-cloud/spring-cloud-sleuth 为什么会出现这个技术&#xff1f; 在微服务框架中&#xff0c;一个由客户…

Vue中如何处理用户权限?

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

决定马里兰州地区版图的关键历史事件

1. 马里兰殖民地的建立&#xff1a; - 1632年&#xff0c;英国国王查理一世将一大片土地赐予塞西尔卡尔弗特男爵&#xff0c;这片土地是为了纪念国王的妻子亨丽埃塔玛丽亚而命名为“马里兰”。卡尔弗特和他的儿子随后建立了马里兰殖民地&#xff0c;这标志着马里兰作为一个独立…

【Java数据结构】——枚举以及Lambda表达式

目录 1 枚举背景及定义 &#x1f6a9;使用 &#x1f388;、switch语句 &#x1f388;、常用方法 &#x1f388;.构造方法 2. Lambda表达式 &#x1f6a9;背景 &#x1f388;Lambda表达式的语法 &#x1f308;函数式接口 &#x1f308;Lambda表达式的基本使用 ❗无参…

RabbitMQ使用

目录 初识MQ 同步通讯和异步通讯​编辑 同步通讯 同步调用存在的问题 总结 同步调用优点&#xff1a; 同步调用的问题&#xff1a; 异步通讯 事件驱动优势 总结 什么是MQ RabbitMQ快速入门 RabbitMQ概述和安装 RabbitMQ结构和概念​编辑 总结 常见消息模型 不同…