结构体成员的易失性访问

问题描述 投票:0回答:1

如果从中断访问标记为

volatile
的结构体成员,是否需要将整个访问链标记为
volatile

例如

struct bar
{
  volatile uint16_t a;
  volatile uint16_t b;
};

struct foo
{
  struct bar bar1;
  struct bar bar2;
};

struct foo foo_arr[10];

void interrupt_handler(void)
{
  struct bar *bar = &foo_arr[0].bar1;
  bar->a = 2;
  bar->b = 3;
}

会员

a
b
标记为
volatile
就足够了吗?我觉得是这种情况,如果不是,我有一些代码需要修复。

c volatile
1个回答
0
投票

通常,在单个结构体成员而不是结构体对象上指定限定符通常会出现问题。在这种情况下,由于每个成员都是

volatile
,因此您也可以执行
volatile struct bar bar1
,从而允许结构体的非
volatile
实例也存在。

但是,如果

a
b
恰好是内存映射的 CPU 寄存器,则不存在它们不是
volatile
的情况,因此通过限定各个成员,可以防止对它们进行任何其他使用在这种特定情况下是一件好事。不过,制作 struct
volatile
也没有什么坏处。


对于这些变量的使用,唯一重要的是用于成员对象的“左值访问”的类型,这必须通过正确限定的类型来完成。例如

* (int*)&bar->a
会调用未定义的行为 - 如果您在声明中使用
const
也会发生同样的情况。

编译器也不能对这个结构做出任何假设,它必须始终将其视为

volatile
。然而,如果每次都明确声明 volatile,那么对于
程序员 
来说,它会更加清晰和自我记录。当意图将某些东西视为
volatile
时,不声明它
volatile
简直就是糟糕的编程风格。但就 C 语言而言,这是没有必要的。

您可以轻松测试:https://godbolt.org/z/rxqPe8abx 注释掉

volatile
,(x86_64 端口)编译器会将写入优化为单个 32 位写入,这不符合 2 个
volatile
变量。通过
volatile
,我们确实获得了 2 个独立的 16 位写入,这是 C 程序执行规则(“抽象机”)所要求的。

© www.soinside.com 2019 - 2024. All rights reserved.