C语言关键字详解:static、const、volatile

在C语言中,staticconstvolatile是三个重要的关键字,它们分别用于不同的场景,具有不同的作用。下面我将详细解释它们的作用并提供示例代码。

1. static关键字

static关键字有三种主要用法:

a) 修饰局部变量(改变存储期)

cpp 复制代码
#include <stdio.h>

void counter() {
    static int count = 0; // 静态局部变量
    count++;
    printf("Count: %d\n", count);
}

int main() {
    counter(); // 输出: Count: 1
    counter(); // 输出: Count: 2
    counter(); // 输出: Count: 3
    return 0;
}

​作用​​:

  • 使局部变量在函数调用之间保持其值

  • 变量存储在静态存储区而非栈上

  • 只初始化一次(在程序启动时)

b) 修饰全局变量(改变链接属性)

cpp 复制代码
// file1.c
static int hidden_var = 42; // 静态全局变量

// file2.c
extern int hidden_var; // 错误!无法访问file1.c中的hidden_var

​作用​​:

  • 限制变量只在定义它的源文件中可见

  • 防止与其他文件中的同名变量冲突

c) 修饰函数(改变链接属性)

cpp 复制代码
// utils.c
static void helper() { // 静态函数
    printf("Helper function\n");
}

// main.c
extern void helper(); // 错误!无法访问utils.c中的helper函数

​作用​​:

  • 限制函数只在定义它的源文件中可见

  • 防止与其他文件中的同名函数冲突

2. const关键字

const关键字用于定义常量,表示值不可修改。

a) 修饰变量

cpp 复制代码
#include <stdio.h>

int main() {
    const int MAX_SIZE = 100;
    // MAX_SIZE = 200; // 错误:不能修改const变量
    
    const float PI = 3.14159;
    // PI = 3.14; // 错误:不能修改const变量
    
    printf("Max size: %d, PI: %.5f\n", MAX_SIZE, PI);
    return 0;
}

b) 修饰指针

cpp 复制代码
#include <stdio.h>

int main() {
    int value = 10;
    int another = 20;
    
    // 指向常量的指针(指针指向的内容不可变)
    const int *ptr1 = &value;
    // *ptr1 = 15; // 错误:不能通过ptr1修改value
    ptr1 = &another; // 正确:可以改变指针指向
    
    // 常量指针(指针本身不可变)
    int *const ptr2 = &value;
    *ptr2 = 15; // 正确:可以修改指向的值
    // ptr2 = &another; // 错误:不能改变指针指向
    
    // 指向常量的常量指针(指针和内容都不可变)
    const int *const ptr3 = &value;
    // *ptr3 = 20; // 错误:不能修改值
    // ptr3 = &another; // 错误:不能改变指向
    
    return 0;
}

c) 修饰函数参数

cpp 复制代码
#include <stdio.h>

// 参数为指向常量的指针,函数内部不能修改str指向的内容
void print_string(const char *str) {
    // str[0] = 'A'; // 错误:不能修改const内容
    printf("%s\n", str);
}

int main() {
    char msg[] = "Hello, World!";
    print_string(msg);
    return 0;
}

3. volatile关键字

volatile关键字告诉编译器不要优化对该变量的访问,因为它可能被程序以外的因素修改。

a) 硬件寄存器访问

cpp 复制代码
// 假设0x1234是硬件寄存器的地址
volatile unsigned int *reg = (unsigned int *)0x1234;

int main() {
    // 读取寄存器值
    unsigned int value = *reg;
    
    // 写入寄存器
    *reg = 0xABCD;
    
    return 0;
}

b) 中断服务程序中的变量

cpp 复制代码
#include <stdio.h>

volatile int flag = 0; // 可能被中断修改的变量

// 模拟中断服务程序
void interrupt_handler() {
    flag = 1;
}

int main() {
    while (!flag) {
        // 等待中断发生
    }
    printf("Interrupt occurred!\n");
    return 0;
}

c) 多线程共享变量

cpp 复制代码
#include <stdio.h>
#include <pthread.h>

volatile int shared_counter = 0; // 多线程共享变量

void *increment(void *arg) {
    for (int i = 0; i < 100000; i++) {
        shared_counter++;
    }
    return NULL;
}

int main() {
    pthread_t t1, t2;
    
    pthread_create(&t1, NULL, increment, NULL);
    pthread_create(&t2, NULL, increment, NULL);
    
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    
    printf("Final counter: %d\n", shared_counter);
    return 0;
}

4.总结对比

关键字 主要作用 典型应用场景
static 改变存储期或链接属性 1. 函数调用间保持状态的局部变量 2. 文件内私有的全局变量和函数
const 定义常量,防止修改 1. 常量值定义 2. 函数参数保护 3. 只读指针
volatile 防止编译器优化 1. 硬件寄存器访问 2. 中断服务程序 3. 多线程共享变量
相关推荐
2401_831824962 小时前
基于C++的区块链实现
开发语言·c++·算法
We་ct2 小时前
LeetCode 918. 环形子数组的最大和:两种解法详解
前端·数据结构·算法·leetcode·typescript·动态规划·取反
愣头不青2 小时前
238.除了自身以外数组的乘积
数据结构·算法
人工智能AI酱3 小时前
【AI深究】逻辑回归(Logistic Regression)全网最详细全流程详解与案例(附大量Python代码演示)| 数学原理、案例流程、代码演示及结果解读 | 决策边界、正则化、优缺点及工程建议
人工智能·python·算法·机器学习·ai·逻辑回归·正则化
WangLanguager3 小时前
逻辑回归(Logistic Regression)的详细介绍及Python代码示例
python·算法·逻辑回归
m0_518019483 小时前
C++与机器学习框架
开发语言·c++·算法
一段佳话^cyx3 小时前
详解逻辑回归(Logistic Regression):原理、推导、实现与实战
大数据·算法·机器学习·逻辑回归
qq_417695053 小时前
C++中的代理模式高级应用
开发语言·c++·算法
xiaoye-duck3 小时前
《算法题讲解指南:动态规划算法--路径问题》--5.不同路径,6.不同路径II
c++·算法·动态规划
ambition202423 小时前
最大子数组和算法全解析:从暴力枚举到动态规划优化
数据结构·c++·算法