volatile struct = struct 不可能,为什么?

volatile struct = struct not possible, why?

struct FOO{
    int a;
    int b;
    int c;
};

volatile struct FOO foo;

int main(void)
{
    foo.a = 10;
    foo.b = 10;
    foo.c = 10;
    struct FOO test = foo;

    return 0;
}

这不会编译,因为 struct FOO test = foo; 生成错误:

error: binding reference of type 'const FOO&' to 'volatile FOO' discards qualifiers

如何在 C++(C++11 之前)中将 volatile struct 复制到另一个 struct

许多人建议只删除 volatile,但在那种情况下我不能那样做,因为我想复制 µC 中当前的 SPI-Reg 设置,而制造商将其声明为 volatile headers。 我想复制这些设置,因为制造商还提供了一个库来使用 EnDat-Communication 的 SPI,而我无权访问 source-code。由于我必须在运行时更改 SPI-Reg-Settings 我想轻松返回库 SPI-settings 而无需再次调用 init_endat()-lib fkt(未指定如果我会发生什么调用它两次)。

我可以为此使用 memcopy() 吗?

根据提示,这是以下问题的副本。

Why am I not provided with a default copy constructor from a volatile?

这是 ill-formed 因为 FOO 有一个隐式复制构造函数定义为:

FOO(FOO const&);

然后你用 volatile FOO 类型的 foo 编写 FOO test = foo;,调用:

FOO(volatile FOO const&);

但是 references-to-volatile 到 references-to-non-volatile 的隐式转换是 ill-formed.

从这里,两个解决方案出现:

  1. 不要对 non-volatile 转化造成波动;
  2. 定义合适的复制构造函数或复制对象成员"manually";
  3. const_cast 可以删除 volatile 限定符,但如果您的基础对象实际上是 volatile,那么使用它是未定义的行为。

Could I possibly use memcopy() for that?

不,你不能,memcpy 与易失性对象不兼容:没有需要 pointers-to-volatile 的重载,如果不调用未定义的行为,你将无能为力。

因此,作为结论,如果不能向 FOO 添加构造函数,最好的办法是定义:

FOO FOO_copy(FOO volatile const& other)
{
    FOO result;
    result.a = other.a;
    result.b = other.b;
    result.c = other.c;
    return result;
}

或者使用 C++11 的 std::tie:

FOO FOO_copy(FOO volatile const& other)
{
    FOO result;
    std::tie(result.a, result.b, result.c) = std::tie(other.a, other.b, other.c);
    return result;
}

您没有提供足够的问题详细信息来进行更准确的评估,但无论您要解决什么问题,解决方案几乎肯定是不使用 volatile。 "Volatile" 意味着值可以从你的脚下改变:两个典型的好用例是从 UNIX 信号处理程序和 memory-mapped 寄存器中改变的变量。 Volatile 不足以用于线程间共享的变量,特别是。

您收到此错误的原因是您的编译器试图找到一个 FOO(volatile FOO&) 复制构造函数,它永远不会自动生成。

提供另一种方法来解决这个问题为什么没有意义,而不仅仅是 C++ 标准说这是无效的:

volatile 的重点是您可以精确控制何时访问哪个变量。这意味着给定 volatile int i, j;i = 1; j = 2;j = 2; i = 1; 不会做同样的事情。编译器不能自由地将一个转换为另一个。这同样适用于读取:给定 volatile int i, j; int x, y;x = i; y = j;y = j; x = i; 不做同样的事情。 volatile 的存在意味着访问 必须 发生在 完全 您指定的顺序。

现在,在您的示例中,struct FOO test = foo; 应该做什么?您从未指定是先阅读 foo.a,然后阅读 foo.b,最后阅读 foo.c,还是首先阅读 foo.c,然后阅读 foo.b,最后 foo.a,或者其他顺序。

如果您愿意,可以这样做:

struct FOO test;
test.a = foo.a;
test.b = foo.b;
test.c = foo.c;

在这里,您明确指定了对foo字段的访问顺序,从而避免了这个问题。