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. 多线程共享变量
相关推荐
通信小呆呆1 小时前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人
benben0442 小时前
强化学习之DQN算法族(基于gymnasium开发)
算法
何以解忧,唯有..3 小时前
Go语言循环语句详解:for、range与循环控制
开发语言·算法·golang
想吃火锅10053 小时前
【leetcode】88.合并两个有序数组js
算法
生成论实验室4 小时前
机器人:一个自主运动的系统
人工智能·算法·语言模型·机器人·自动驾驶·agi·安全架构
Qres8214 小时前
算法复键——树状数组
数据结构·算法
H178535090964 小时前
SolidWorks第四部分_直接实体建模特征9_替换面原理
线性代数·算法·机器学习·3d建模·solidworks
不会就选b4 小时前
算法日常・每日刷题--<二分查找>3
算法
绿算技术5 小时前
Mooncake 与绿算ForinnBase GroundPool如何联手打破推理僵局?
科技·算法·架构