当仅在中断期间读取变量时是否需要 volatile
Is volatile needed when variable is only read during interrupt
C 标准规定,当变量的值有可能在程序的正常执行流程之外发生变化时,应在变量的定义中使用 volatile 关键字。
如果在正常执行流程期间更改(写入)全局变量并且仅在该正常流程之外(在中断中)读取。这个变量是否需要 volatile ?为什么?
If a global variable is changed (written) during normal execution flow and only read outside this normal flow (in an interrupt). Does this variable need to be volatile?
绝对是。
And why?
确保正确执行中断处理程序(而不是正常流程)。
让我详细说明。
假设您有一个这样的变量:
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 以防止编译器干预程序。
C 标准规定,当变量的值有可能在程序的正常执行流程之外发生变化时,应在变量的定义中使用 volatile 关键字。
如果在正常执行流程期间更改(写入)全局变量并且仅在该正常流程之外(在中断中)读取。这个变量是否需要 volatile ?为什么?
If a global variable is changed (written) during normal execution flow and only read outside this normal flow (in an interrupt). Does this variable need to be volatile?
绝对是。
And why?
确保正确执行中断处理程序(而不是正常流程)。
让我详细说明。
假设您有一个这样的变量:
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 以防止编译器干预程序。