kssmodjywjt6401882219.png
8 q9 r2 ~& Y6 U0 N
5 e% x( k! w% g6 y! y8 c8 Q当你使用 volatile 关键字时,你告诉编译器该变量的值可能会在程序的执行过程中被外部因素更改,因此编译器不应该对该变量的读写进行优化。下面是一些使用 volatile 的例子,以及对它们的一些文字描述:
: f) J0 p P( N; `1,防止编译器优化#include int main() { int a = 0; while (a == 0) { // 此处的循环条件可能在外部被修改,使用 volatile 防止编译器优化 } printf("Loop exited!
- K+ ]9 ]$ N0 i0 R* x# z. R"); return 0;}这个例子中,a 的值可能会在循环外部被修改,但是由于循环内没有对 a 进行修改的语句,编译器可能会认为 a 的值在循环中永远不会变化,进而优化掉整个循环。通过使用 volatile,我们告诉编译器不要对这个变量的读写进行优化。' ^% k5 S( j" z( L
2. 提醒编译器不要缓存#include #include #include volatile int flag = 1; // 用于标识是否可以退出循环void *threadFunction(void *arg) { sleep(2); // 模拟一些操作 flag = 0; // 线程中修改 flag 的值 return NULL;}int main() { pthread_t tid; pthread_create(&tid, NULL, threadFunction, NULL); while (flag) { // 在循环中读取 flag 的值,使用 volatile 防止编译器缓存 } printf("Thread signaled exit! v8 V3 E0 `# E, O
"); pthread_join(tid, NULL); return 0;}在这个例子中,flag 的值在另一个线程中被修改。由于涉及多线程,编译器可能会对 flag 进行缓存优化。通过使用 volatile,我们提醒编译器不要对这个变量进行缓存,而是每次都从内存中重新加载。
2 U& h7 T6 g0 O) {: I* Z3. 内存映射的硬件寄存器#include volatile unsigned int *hardwareRegister = (volatile unsigned int *)0x12345678;int main() { unsigned int value = *hardwareRegister; // 从硬件寄存器读取值 // 对硬件寄存器进行操作... *hardwareRegister = 42; // 将值写入硬件寄存器 return 0;}在这个例子中,hardwareRegister 是一个指向内存映射硬件寄存器的指针。硬件寄存器的值可能在程序执行期间被硬件修改,因此我们使用 volatile 保证了对硬件寄存器的读写不会被编译器优化,而是每次都从内存中重新加载。( r' L7 L- z3 M% M; }
==========5 r3 b0 y. W Q V% \" O
往期回顾:STM32单片机实现固件在线升级
% |$ @2 |% Q# N0 MFreeRTOS中Systick的问题
/ e" A+ v+ A) d* V9 \CH32内部参考电压的笔记 v* r: q1 A) ~+ B: f
strlen和sizeof的异同6 }& F+ G; Q3 d' F3 S R
STM32CubeMx的串口DMA收发数据 ?1 M5 t) M) |" A+ Z6 l
==========2 j- u7 t" I! t( a' V0 {$ F
7 v' B8 K0 y/ m" R+ o, v
1glajgamaq46401882319.png
: m. ~ J* j2 x& R& ~/ G
/ D* k' Q+ }1 Z, U$ }- {
tmdisz4dd4x6401882420.png
6 b9 O, \7 N/ Y* l/ _6 l1 ?) y0 T! J3 {, l# D, ^
25m3ke1svxw6401882520.png
|