C 中 volatile 非静态局部变量的原因

Reason for volatile nonstatic local variable in C

参考以下代码:

void calledFunction(volatile uint8_t **inPtr);
volatile uint8_t buffer[] = {0,0,0,0,0,0}; 

volatile uint8_t *headPtr = buffer;

void foo(void)
{
    volatile uint8_t *tmpPtr = NULL;

    tmpPtr = headPtr;

    //This function modifies tmpPtr
    calledFunction(&tmpPtr);

    headPtr = tmpPtr;
    return;
}

这是我试图使中断安全的代码的简化版本,我不确定为什么将此本地定义为 volatile。我知道没有性能原因(即保证此函数至少为 O(n)),因为此函数 应该 运行 尽可能高效。

这个函数可以在主执行和内部中断中调用,但是由于 tmpPtr 是一个非静态局部变量,它不应该被 foo() 的任何其他实例修改。

在此上下文中我看不到任何需要 volatile 关键字的访问模式。

简而言之,函数 foo()tmpPtrvolatile 关键字的用途是什么?

编辑:忘记函数参数中的 &

EDIT2:我继承了这段代码,需要修改。 我的主要问题是 volatile 关键字是否有任何特别有效的理由出现在这种情况下。

EDIT3:添加了 calledFunction()

的原型

EDIT4:在原始代码中添加了 重要 说明,即 headPtrbuffer 都有 volatile

tmpPtrvolatile 的原因是 tmpPtr 需要引用 volatile uint8_t,而不是因为 tmpPtr 本身就是 volatile (不是)。

正如@Eugene Sh. 最初指出的那样,这个问题是由于在定义 volatile 指针和变量时语法上的误解而出现的。 对指向 volatile 指针和 volatile 指针的语法有很好的解释。

Volatile 限制编译器在访问(读取或写入)此指针指向的数据时进行优化。

这经常出现在嵌入式或中断中,因为内存映射外围设备无法优化通常“无关”的读取或写入。

例如,

int32_t variable = 0;
variable = 1;
variable = 2;
variable = 3;

优化编译器会跳过将变量的值设置为 0、1 和 2,而只是将其设置为 3。这通常没问题,但如果我们不是写入普通变量,而是写入内存映射端口,我们实际上希望每个写入都发生。

这甚至可能发生在硬件接口世界之外。如果一个单独的线程在循环中寻找要设置为 2 的变量,优化编译器会阻止这种情况发生。

它是本地的事实不是 material。只是大多数 volatile 的用例都是用翻译单元(或使用 extern 的交叉翻译单元)作用域实现的。

两个例子是内存映射寄存器定义(结构通常是全局的,通常在头文件中,并且通常指向结构的指针的实例是全局的,尽管它不一定是全局的)和标志就像我们的线程示例。

我不提倡这两种设计,但您会在嵌入式开发中经常遇到它。