1-5 C语言 - 类型修饰符关键字const和volatile的概念及使用(超详细)

本节重点讲述类型修饰符关键字const和volatile的概念及使用,如果想详细了解关键字的同学点击下方链接进行跳转

1-1 C语言 - 关键字及其使用(数据类型)-CSDN博客

1-2 C语言 - 控制语句关键字-CSDN博客

1-3 C语言 - 控制语句的使用注意事项(这些绝对是您经常出错的地方)-CSDN博客

1-4 C语言 - 存储类别关键字及其使用(超详细)-CSDN博客

目录

const 关键字

const 的使用场景

示例 1:声明常量

示例 2:指针修饰

示例 3:函数参数

volatile 关键字

volatile 的使用场景

示例 1:硬件寄存器

示例 2:多线程编程

示例 3:信号处理

注意事项及易错点

const 使用

volatile 使用


const 关键字

const 关键字用于声明常量,其作用是防止变量的值被修改。这有助于提高代码的安全性和可读性,同时也允许编译器进行更多的优化。

const 的使用场景

  1. 常量数据:声明不变的常量数据。
  2. 指针修饰:用于修饰指针,表示指针所指向的数据或指针本身是常量。
  3. 函数参数:在函数参数中使用 const,表示函数不会修改传入的参数。

示例 1:声明常量

const int MAX_SIZE = 100;

MAX_SIZE 被声明为常量,值为 100,之后的代码中不能修改 MAX_SIZE 的值。

示例 2:指针修饰

const int* ptr; // ptr 是指向 const int 的指针,不能通过 ptr 修改 int 的值
int* const ptr2; // ptr2 是 const 指针,不能修改 ptr2 本身,但可以修改其指向的值
const int* const ptr3; // ptr3 是指向 const int 的 const 指针,不能修改 ptr3 或其指向的值

示例 3:函数参数

void printArray(const int* arr, int size) {for (int i = 0; i < size; ++i) {printf("%d ", arr[i]);}// arr[i] = 5; // 错误:不能修改 const int* 指针所指向的数据
}

函数 printArray 接收一个 const int* 参数,这表示 printArray 函数不会修改 arr 数组的内容。

volatile 关键字

volatile 关键字用于声明一个变量的值可能会被程序外部的因素(如硬件或其他线程)改变。这告诉编译器,每次访问该变量时都必须从内存中读取最新的值,而不是使用寄存器中的缓存值。

volatile 的使用场景

  1. 硬件寄存器:当变量对应硬件寄存器时,硬件可能在后台改变寄存器的值。
  2. 多线程编程:在多线程编程中,当一个变量在不同的线程之间共享并可能被任意线程修改时。
  3. 信号处理:在处理异步信号时,信号处理函数可能修改某些全局变量。

示例 1:硬件寄存器

volatile int* port = (volatile int*)0x4000; // 假设 0x4000 是硬件端口地址

port 是一个指向硬件寄存器的指针,volatile 确保每次访问 *port 都获取最新的值。

示例 2:多线程编程

volatile int flag = 0;void thread1() {flag = 1; // 修改 flag 的值
}void thread2() {while (flag == 0) {// 等待 flag 变为 1}// 继续执行
}

flag 被声明为 volatile,确保 thread2 能够正确读取到 thread1 修改后的值。

示例 3:信号处理

volatile sig_atomic_t signalFlag = 0;void signalHandler(int signal) {signalFlag = 1;
}int main() {signal(SIGINT, signalHandler);while (!signalFlag) {// 等待信号}printf("Signal received.\n");return 0;
}

signalFlag 被声明为 volatile,确保主程序在信号处理程序修改 signalFlag 后能立即读取到更新的值。

注意事项及易错点

constvolatile 关键字在 C/C++ 编程中的正确使用可以提高代码的安全性、可读性和性能,但在使用过程中也有一些需要注意的事项和易错点。

const 使用

  • 常量初始化

    • const 变量必须在声明时进行初始化,因为它们的值不能在之后被修改。
    • const int x; // 错误:未初始化
      const int y = 10; // 正确:在声明时初始化
      
  • 指针和 const

    • 指针与 const 的组合可能会引起混淆,特别是理解指针本身是否是常量以及指针所指向的数据是否是常量。
    • const int* p1; // 指向 const int 的指针,不能通过 p1 修改 int 的值
      int* const p2; // const 指针,不能修改 p2 本身,但可以修改其指向的值
      const int* const p3; // 指向 const int 的 const 指针,不能修改 p3 或其指向的值
      
  • 函数参数

    • 使用 const 修饰函数参数时,确保理解其含义:传递 const 指针意味着函数不能修改指针所指向的数据,但可以修改指针本身。
    • void foo(const int* p); // p 是指向 const int 的指针,不能通过 p 修改 int 的值
      
  • 返回值

    • 如果函数返回指针,使用 const 可以防止调用者修改函数返回的数据。
    • const int* getArray();
      
  • volatile 使用

  • 避免优化

    • 使用 volatile 的目的是告诉编译器不要优化对变量的访问,以确保每次访问都是从内存中读取最新的值。
    • volatile int flag = 0;
      
  • 硬件寄存器

    • 在嵌入式编程中,通常会将硬件寄存器声明为 volatile,以确保每次访问寄存器时都能读取到最新的硬件状态。
    • volatile int* port = (volatile int*)0x4000;
      
  • 多线程编程

    • 在多线程编程中,使用 volatile 确保变量的修改在不同线程之间可见。但需要注意的是,volatile 并不能保证线程安全,通常需要与其他同步机制(如互斥锁、信号量等)结合使用。
    • volatile int flag = 0;
      
  • 信号处理

    • 在信号处理函数中使用 volatile 确保信号处理程序修改的全局变量能被主程序正确读取。
    • volatile sig_atomic_t signalFlag = 0;
      

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

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

相关文章

2024鸿蒙开发【面试题库】,转岗看这一篇就够了

鸿蒙面试浪潮来袭&#xff0c;你是否也想着利用这次机会去实现&#xff0c;跳槽涨薪的梦呢&#xff1f; 如果关注了华为鸿蒙的人应该知道&#xff1a;鸿蒙开发岗位需求飙升6倍&#xff01; 可想而知该岗位前景多么广阔&#xff0c;为此就为大家整理些&#xff08;鸿蒙HarmonyO…

springboot社区旧物回收系统-计算机毕业设计源码94813

目 录 摘要 1 绪论 1.1 研究背景 1.2研究意义 1.3论文结构与章节安排 2 社区旧物回收系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 社…

SQL面试题练习 —— 计算用户首单是即时单的比例

目录 1 题目2 建表语句3 题解 题目来源&#xff1a;美团。 1 题目 在外卖订单中&#xff0c;有时用户会指定订单的配送时间。现定义&#xff1a;如果用户下单日期与期望配送日期相同则认为是即时单&#xff0c;如果用户下单日期与期望配送时间不同则是预约单。每个用户下单时间…

gogs的安装和使用(docker)

1.docker安装gogs 1.1 拉取gogs镜像 docker pull gogs/gogs #也可改为自己需要的版本号 1.2 创建存储目录 mkdir /root/gogs 1.3 运行镜像 docker run --namegogs -d -p 10022:22 -p 13000:3000 -v /root/gogs:/data gogs/gogs 1.3.1 指令解析 --namegogs: 指定名称…

文章复现 创新点 代码改进跑通 深度学习

文章复现 创新点 代码改进跑通 深度学习 SCI代码复现 文章复现 数据处理、数据分析、算法、数据结构data structure、机器学习machine learning、深度学习deep learning。创新改进&#xff0c;算法提升 python环境配置 &#xff0c;深度学习代码调试 、代码复现&#xff0c;py…

数据库优化

文章目录 一、如何定位慢查询二、分析慢SQL&#xff08;一&#xff09;Explain 三、索引介绍&#xff08;一&#xff09;数据结构1、二叉树2、红黑树3、B树4、B 树 &#xff08;二&#xff09;聚集索引&二级索引&#xff08;三&#xff09;索引的创建原则&#xff08;四&am…

ElementUI元件库在Axure中使用

一、ElementUI元件库介绍 ElementUI 是一套为开发者、UI/UX设计师和产品经理准备的基于Vue 2.0的桌面端组件库。它以其优雅的设计和丰富的组件&#xff0c;极大地提升了Web应用的开发效率与用户体验。ElementUI的组件设计精致且符合现代UI规范&#xff0c;包括按钮、表单、弹窗…

指针(一)

指针变量&#xff1a;用来存放地址的变量。 这里讲一下为什么两位为一个字节&#xff1a;首先这是一个十六进制的地址&#xff0c;再十六进制中的F&#xff08;15&#xff09;用二进制表示是需要四位&#xff08;1111&#xff09;&#xff0c;所以一位代表四个bit&#xff0c;两…

JavaEE 第7节 线程饥饿及其解决办法

目录 一、什么是线程饥饿&#xff1f; 二、线程饥饿的解决办法 *wait()与notify()方法解决线程饥饿 1、wait(等待) 2、notify(通知) 1&#xff09;notify 2&#xff09;notifyAll 3&#xff09;关于wait方法的一些补充 1、wait的方法的三个功能是原子性的&#xff1a;…

【mysql 第二篇章】请求到真正执行 SQL 到底是一个怎么样的过程?

从用户调用到SQL执行的流程中间发生了什么事情 1、网络请求使用 线程 来处理&#xff0c;当数据库连接池中监听到有连接请求&#xff0c;这个时候会分配一个线程来处理。 2、SQL接口 负责接收 SQL 语句&#xff0c;当线程监听到有请求和读取数据的之后&#xff0c;将 SQL 语句…

鸿蒙(API 12 Beta3版)【视频解码】 音视频编码

开发者可以调用本模块的Native API接口&#xff0c;完成视频解码&#xff0c;即将媒体数据解码成YUV文件或送显。 当前支持的解码能力如下&#xff1a; 视频硬解类型视频软解类型AVC(H.264)、HEVC(H.265)AVC(H.264) 视频解码软/硬件解码存在差异&#xff0c;基于MimeType创建…

【实现100个unity特效之15】最简单的方法使用shader graphs实现2d非像素和像素树叶草的随风摇摆效果

文章目录 前言非像素树叶草飘动效果新建材质效果像素树叶草飘动效果参考完结 前言 本文只是实现一个简单版本的2d树叶草随风摇摆的效果&#xff0c;如果你想要实现更加复杂的效果&#xff0c;包括2d互动草&#xff0c;你可以参考我之前的文章&#xff1a; 【推荐100个unity插件…

Docker 入门全攻略:安装、操作与常用命令指南

目录 Docker 入门全攻略&#xff1a;安装、操作与常用命令指南 一、引言 二、Docker 下载与安装 2.1 Docker 的系统要求 2.2 安装步骤 ①对于 Windows 的安装指南 ②对于 macOS 的安装指南 ③对于 Linux 的安装指南 三、Docker 的基本概念 3.1 镜像&#xff08;Image…

java消息队列ActiveMQ

安装 前置条件 activemq的运行依赖于jdk&#xff0c;需要提前安装jdk如果已经安装了jdk&#xff0c;需要根据jdk的版本来选择对应的版本进行安装activemq版本对应在官网上&#xff0c;使用java -version 看jdk的版本注意&#xff1a;jdk和mq的版本不一致会报错&#xff0c;电脑…

MySQL笔记-基础篇(一):查询

博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 MySQL是一种广泛使用的关系型数据库管理系统&#xff0c;它基于结构化查询语言&#xff08;SQL&#xff09;来管理和操作数据。下面将依次探讨MySQL查询的各个方面&#xff0c;确保理解扎实&#xff0c;能够在实…

计算机视觉——凸包计算

现在有一大堆点&#xff0c;然后你要找出一个可以围住这些点且面积最小的凸多边形&#xff0c;这个凸多边形称为凸包。 显而易见&#xff0c;如果要面积最小&#xff0c;那凸包的顶点势必得是这一大堆点的几个点&#xff0c;你也可以想成是用一条橡皮筋把这些点圈起来。 先把各…

Python中的 `break` 语句:掌握循环控制的艺术

Python中的 break 语句&#xff1a;掌握循环控制的艺术 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕…

【大模型系列篇】论文解读:Transformer - Attention Is All You Need (2017)

Attention Is All You Need (Transformer) 是当今大模型初学者必读的一篇论文&#xff0c;已经有不少业内大佬都翻译解读过这篇论文&#xff0c;此处仅作为自己学习的记录。该论文是由谷歌机器翻译团队于2017年发表在NIPS &#xff0c;提出了一个只基于attention的结构来处理序…

【iOS】OC关键字总结及底层原理(上)

目录 线程安全相关的关键字atomic&nonatomic 作用域相关的关键字static、extern、const&auto 读写权限相关和指定方法名的关键字内存管理相关的关键字&#xff08;或方法&#xff09;1. 引用计数的存储SideTableretain方法源码分析release方法源码分析dealloc方法源码分…

嵌入式初学-C语言-十九

指针的引入 为函数修改实参提供支持为动态内存管理提供支持为动态数据及结构提供支持为内存访问提供另一种途径 指针的概述 内存地址&#xff1a; 系统为了内存管理的方便将内存划分为一个个内存单元&#xff08;一个内存单元占一个字节&#xff09;&#xff0c;并为每一个…