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=FOO使用volatile 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;