C标准规定,如果变量的值可能在程序的正常执行流程之外发生变化,则应在变量的定义中使用volatile关键字。
如果在正常执行流程中更改(写入)了全局变量,并且仅在该正常流程之外(在中断中)读取。这个变量需要可变吗?为什么?
答案 0 :(得分:5)
如果在正常执行流程中更改(写入)了全局变量,并且仅在该正常流程之外(在中断中)读取。这个变量需要可变吗?
是的。
为什么?
为了确保正确执行中断处理程序(而不是正常流程)。
让我详细说明。
想象一下,您有一个像这样的变量:
int x;
您正在程序的正常流程中修改此变量,如下所示:
void modify(int *x){...some code here...}
在中断服务程序中,您正在读取变量。
请记住,中断可以异步发生(任何时候)。还请记住,编译器首先会将您的代码转换为一系列机器指令,看起来像这样:
load val from mem to register
perform modification operations
store value from registers to memory
perform other operations where the variable is used
现在,编译器可以优化该程序,以减少这样的内存读写次数:
load value
perform modifications
use value
...
modify register content
...
use
...
keep using value from the registers without ever storing in the memory.
在这种情况下,如果发生中断(请注意,中断上下文通常与正常上下文不同,因此在许多体系结构中具有不同的寄存器集(例如arm ...)),它将尝试从内存中读取变量的值。但是由于编译器的优化,内存的内容从未改变过。
因此,ISR会读取一个旧值(更糟糕的是-我们不能肯定地说一个值有多旧),这会导致意外的行为。
因此,应将变量声明为volatile,以防止编译器干预程序。