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;
      

  • 40
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值