c - C 中的 volatile 和变量修改

标签 c volatile

一个结构体 TsMyStruct 作为一些函数的参数给出:

typedef struct
{
    uint16_t inc1;
    uint16_t inc2;
}TsMyStruct;


void func1(TsMyStruct* myStruct)
{
    myStruct->inc1 += 1;
}

void func2(TsMyStruct* myStruct)
{
    myStruct->inc1 += 2;
    myStruct->inc2 += 3;
}

func1 在非中断上下文中调用,func2 在中断上下文中调用。 func2 的调用堆栈以中断 vector 为起点。 C 编译器不知道可以调用 func2(但代码不被视为“未使用”代码,因为链接器在中断 vector 表内存部分需要它),因此可以优化一些在 func2 之外读取 myStruct->inc2 的代码,以防止 myStruct->inc2 从 ram 重新加载。对于 C 基本类型是正确的,但是对于 inc2 结构成员或某些数组...是正确的吗?函数参数也是如此吗?

作为一般规则,我可以说“在中断上下文中修改并在其他地方读取的每个内存区域(基本类型?或不是?)都必须声明为 volatile ”?

最佳答案

是的,在中断处理程序内部和外部使用的任何内存都应该是volatile,包括结构和数组,以及作为函数参数传递的指针。假设您的目标是单核设备,则不需要额外的同步。

不过,您必须考虑到 func1 可能在任何地方被中断,如果您不小心,这可能会导致不一致的结果。例如,考虑一下:

void func1(volatile TsMyStruct* myStruct)
{
    myStruct->inc1 += 1;
    if (myStruct->inc1 == 4)
    {
        print(myStruct->inc1); // assume "print" exists
    }
}

void func2(volatile TsMyStruct* myStruct)
{
    myStruct->inc1 += 2;
    myStruct->inc2 += 3;
}

由于中断是异步的,这可能会打印不同于 4 的数字。例如,如果 func1 在检查之后但在 print 调用之前被中断,就会发生这种情况。

关于c - C 中的 volatile 和变量修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49418327/

相关文章:

c - 将枚举指针传递给整数指针输出参数

c - 从c中的随机访问文件中读取

c - C 中的 typedef union 和 eclipse 自动完成

c++ - C 中的 volatile 关键字是否正确需要特殊的硬件支持才能工作?

java - volatile 会保护我免受所有幕后多线程危害吗?

c - NTP实现C

C - chmod() 不改变权限

c++ - 如何用非 volatile 结构初始化 volatile 结构?

java - ConcurrentHashMap 更改对所有线程可见?

java - volatile 变量和发生在订购前