本篇文章记录我学习C语言进阶知识——C语言关键字,旨在记录分享,希望我的分享能带给你不一样的收获!
目录
一、关键字----volatile
volatile 是易变的、不稳定的意思。很多人根本就没见过这个关键字,不知道它的存在。
也有很多程序员知道它的存在,但从来没用过它。我对它有种“杨家有女初长成,养在深闺
人未识” 的感觉。
在C语言中,volatile
是一个关键字,用于告诉编译器某个变量的值可能会在程序的执行过程中被外部因素改变。这个关键字的使用能够确保编译器不会对这样的变量进行优化,以避免潜在的逻辑错误。
volatile 关键字和 const 一样是一种类型修饰符, 用它修饰的变量表示可以被某些编译器
未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编
译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
1、volatile
关键字的作用
防止优化:
- 编译器在优化代码时可能会假设变量的值在程序的某个时刻不会改变。因此,它可能会将变量的值缓存起来,减少对内存的访问。使用
volatile
修饰的变量会强制编译器每次都从内存中读取变量的值,而不是使用缓存的值。
硬件寄存器访问:
- 在嵌入式编程中,
volatile
经常用于访问硬件寄存器,因为这些寄存器的值可能由外部硬件改变。例如,某些寄存器可能会在硬件事件发生时自动更新。
多线程编程:
- 在多线程程序中,如果一个变量在一个线程中被修改,其他线程可能需要看到这些修改。
volatile
可以帮助确保变量的最新值被读取,但请注意,volatile
只是确保每次访问时从内存中读取变量的值,而不是保证线程安全。
2、volatile
的使用示例
【1】硬件寄存器:
volatile int *hardware_register = (int *)0x4000; // 硬件寄存器的地址
int value = *hardware_register; // 从硬件寄存器读取值
【2】中断服务例程:
volatile int flag = 0;
void interrupt_handler() {
flag = 1; // 中断处理程序设置标志
}
void main() {
while (!flag) {
// 等待中断设置 flag
}
// flag 被中断服务程序设置为 1,循环结束
}
【3】多线程变量(注意 volatile
并不替代其他同步机制,如互斥锁):
volatile int shared_variable = 0;
void thread_function() {
while (shared_variable == 0) {
// 等待其他线程改变 shared_variable
}
// shared_variable 被改变,退出循环
}
二、关键字---extern
extern
关键字在 C 语言中用于声明一个变量或函数是在其他文件中定义的。它告诉编译器该标识符的定义在其他地方,这样可以在多个文件间共享变量或函数。
1、关键字extern作用
声明变量:
- 当在一个文件中声明一个外部变量时,使用
extern
来告诉编译器这个变量的定义在其他地方。声明函数:
extern
也用于声明函数,虽然函数声明默认是外部的,因此常常不显式使用extern
,但可以用来提高可读性。
2、关键字extern的用法示例
1. 变量声明
在 file1.c
中定义变量:
int global_var = 10;
在 file2.c
中声明变量:
extern int global_var; // 声明在 file1.c 中定义的变量
void print_var() {
printf("%d\n", global_var);
}
在
file2.c
中使用global_var
,但不定义它,编译器会知道它在file1.c
中定义。
2. 函数声明
在 file1.c
中定义函数:
void greet() {
printf("Hello from file1.c\n");
}
在 file2.c
中声明函数:
extern void greet(); // 函数声明
int main() {
greet(); // 调用在 file1.c 中定义的函数
return 0;
}
注意事项
定义与声明:
extern
用于声明而不是定义。定义变量时不应使用extern
,但在声明时可以使用它以指示变量的定义在其他地方。头文件:
- 通常将
extern
变量的声明放在头文件中,以便在多个源文件中共享这些变量或函数。编译链接:
- 确保所有源文件正确链接,否则可能会导致链接错误。