易失性结构体语义

86

如果一个结构体类型的变量实例被声明为volatile(如果其字段在可重入代码中被访问),这是否足够,或者必须声明特定字段为volatile?

换句话说,以下两种方式之间有什么语义差异(如果有):

typdef struct {
  uint8_t bar;
} foo_t;

volatile foo_t foo_inst;
并且
typedef struct{
  volatile uint8_t bar;
} foo_t;

foo_t foo_inst;

我认识到将指针类型的变量声明为volatile(例如,volatile uint8_t * foo)仅仅是告诉编译器指向 foo 的地址可能会发生改变,而不对 foo 指向的值做出任何陈述。我不清楚是否也适用于结构类型的变量。


在 C 中两个版本没有区别,但是在 C++ 中它们是不同的,正如这个例子所示:https://godbolt.org/z/fYhzMKqjj 你可以自己试一试。 - Daniel K.
2个回答

89
在你的例子中,这两者是相同的。但问题围绕指针展开。
首先,volatile uint8_t *foo;告诉编译器指向的内存是易变的。如果要将指针本身标记为易变,需要使用uint8_t * volatile foo; 这就是将结构体标记为易变与将单个字段标记为易变之间的主要区别。如果你有:
typedef struct
{
    uint8_t *field;
} foo;

volatile foo f;

那会像这样:

typedef struct
{
    uint8_t * volatile field;
} foo;

而不是像这样:

typedef struct
{
    volatile uint8_t *field;
} foo;

2
如果该字段是 uint8_t field[10],当您将结构标记为 volatile 时,底层数据是否被标记为 volatile 或者 "effective" 指向 field 的指针被标记为 volatile? - Mark Elliot
3
基础数据是不稳定的。需要考虑的一件事是,“有效”指针不可修改(它始终是第一个元素的地址),因此在这方面,volatile没有意义。 - R Samuel Klatchko
1
结构体“定义”可以标记为volatile吗?还是只能与typedef或实例变量保持一致? - sherrellbc

31
如果您使用"volatile"声明结构体,那么它的所有成员也会被声明为"volatile"。

7
在侧边栏上,对于const同样适用。 - Alon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接