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

C++ volatile struct=struct不可能,为什么?,c++,struct,volatile,C++,Struct,Volatile,这不会编译,因为 struct FOO test=FOO 生成一个错误: 错误:将“const FOO&”类型的引用绑定到“volatile FOO” 丢弃限定符 C++如何在C++中(C++ 11之前)将易失结构> 复制到另一个结构> /代码>? 许多人建议只删除volatile,但在这种情况下我不能这样做,因为我想在µC内复制当前的SPI Reg设置,而这是由制造商标题声明为volatile的。 我想复制这些设置,因为Manufacturer还提供了一个库来使用SPI进行EnDat通信,而

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

错误:将“const FOO&”类型的引用绑定到“volatile FOO” 丢弃限定符

<> C++如何在C++中(C++ 11之前)将<代码>易失结构> <代码>复制到另一个<代码>结构> /代码>? 许多人建议只删除volatile,但在这种情况下我不能这样做,因为我想在µC内复制当前的SPI Reg设置,而这是由制造商标题声明为volatile的。 我想复制这些设置,因为Manufacturer还提供了一个库来使用SPI进行EnDat通信,而我没有访问源代码的权限。由于我必须在运行时更改SPI Reg设置,因此我希望在不再次调用init_endat()-lib fkt的情况下轻松返回到库SPI设置(如果我调用两次,会发生什么情况尚未确定)

我可以用memcopy()来做这个吗

正如所建议的,这是以下问题的副本


这是格式错误的,因为
FOO
有一个隐式复制构造函数,定义为:

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;
}
然后编写
footest=FOOvolatile foo
类型的
foo
,调用:

FOO(FOO const&);
但对volatile的引用到对非volatile隐式转换的引用是错误的

由此产生了两种解决方案:

  • 不要将易失性转换为非易失性
  • 定义合适的复制构造函数或“手动”复制对象成员
  • const_cast
    可以删除volatile限定符,但如果基础对象实际上是volatile的,则使用该限定符是未定义的行为
  • 我可以用memcopy()来做这个吗

    不,您不能,
    memcpy
    与volatile对象不兼容:它不会重载指向volatile的指针,如果不调用未定义的行为,您将无能为力

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

    FOO(volatile FOO const&);
    
    或使用C++11:


    您没有提供足够的问题详细信息来进行更精确的评估,但是您试图解决的任何问题的解决方案几乎肯定不是使用
    volatile
    。“Volatile”意味着值可以从脚下更改:两个典型的良好用例是UNIX信号处理程序和内存映射寄存器中更改的变量。特别是,Volatile对于线程之间共享的变量是不够的


    你之所以得到这个错误是因为你的编译器试图找到一个<代码> FO(FAND FoO)复制构造器,它从来没有自动生成。< /P> < P>给另一个答案,来解释为什么这没有意义,而不是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
    ,或者其他顺序

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

    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;
    }
    

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

    也许第一个问题是您想要volatile做什么?(提示:您可能不知道)使用
    volatile
    是错误的概率大约为100%。您正在处理内存映射硬件吗?我不这么认为。从您的词汇表中删除
    volatile
    。@JiveDadson volatile还有许多其他有效的用法(性能测试、数学计算、信号处理程序等等)。我并不是说OP做了其中一个——只是反对volatile在硬件的低级操作之外没有用处的观点。哪个编译器会给你这个错误?此外,在清除包含一些敏感数据(例如加密密钥)的内存时,使用“volatile”也很有用,即使清除后没有代码读取此内存。请参阅:。我认为memcpy也会遇到同样的错误。也许以成员身份复制是唯一的选择。我喜欢这种方法。这不是
    volatile
    的意思。这就是std::atomic和内存顺序std::memory_order_seq_cst的意思。VisualC++对内存进行了一些顺序保证,除非你设置了一个标准的符合性标志,但是承诺并没有那么强。code>volatile
    仅用于访问内存映射硬件,我猜UNIX信号处理程序。@JiveDadson你对我的答案的理解比我实际写的要多。我写的正是volatile的意思。Pr.1:“对易失性对象的访问严格按照抽象机器的规则进行评估”,@ HVD <代码> Value保证个别访问不会被优化,但不会阻止它们与其他人重新排序(即, Value在C++中不建立在订单之前发生)。。我喜欢
    volatile
    对某些开发人员来说是多么神秘:)@JAB你知道编译器是如何按照“仿佛”规则对指令重新排序的吗?这个规则不适用于易失性对象(参见上面引用的
    [intro.execution]/8.1
    )。你所说的与multi-t有关
    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;
    }
    
    struct FOO test;
    test.a = foo.a;
    test.b = foo.b;
    test.c = foo.c;