mak*_*kum 23 c++ struct volatile
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;
}
Run Code Online (Sandbox Code Playgroud)
这将无法编译,因为
struct FOO test = foo;
生成错误:
错误:'const FOO&'类型的绑定引用到'volatile FOO'会丢弃限定符
如何在C++中复制volatile struct到另一个struct(在C++ 11之前)?
许多人建议只删除volatile,但在这种情况下我不能这样做,因为我想在μC内复制当前的SPI-Reg设置,并且这被制造商标题声明为volatile.我想复制这些设置,因为制造商还提供了一个库来使用SPI进行EnDat-Communication,而我无法访问源代码.由于我必须在运行期间更改SPI-Reg-Settings,因此我希望能够轻松返回到库SPI设置,而无需再次调用init_endat() - lib fkt(如果我将其调用两次,则未指定会发生什么).
我可以使用memcopy()吗?
如上所述,这是以下问题的副本.
YSC*_*YSC 23
这是错误的,因为FOO有一个隐式复制构造函数定义为:
FOO(FOO const&);
Run Code Online (Sandbox Code Playgroud)
你FOO test = foo;用foo类型写volatile FOO,调用:
FOO(volatile FOO const&);
Run Code Online (Sandbox Code Playgroud)
但是对引用到非易失性隐式转换的引用 - 易失性是不正确的.
从这里出现两种解决方案:
const_cast 可以删除volatile限定符,但这是未定义的行为,如果你的底层对象是有效的volatile.我可以使用memcopy()吗?
不,你不能,memcpy与volatile对象不兼容:thre不会引起指针到易失性的重载,没有调用未定义的行为就没有什么可以做的.
所以,作为一个结论,如果你不能添加一个构造函数,你最好的镜头FOO是定义:
FOO FOO_copy(FOO volatile const& other)
{
FOO result;
result.a = other.a;
result.b = other.b;
result.c = other.c;
return result;
}
Run Code Online (Sandbox Code Playgroud)
或者使用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;
}
Run Code Online (Sandbox Code Playgroud)
小智 19
为了给出答案的另一种方法,解决为什么这没有意义,而不仅仅是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;
Run Code Online (Sandbox Code Playgroud)
在这里,您明确指定了对foo字段的访问顺序,以避免出现此问题.