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.
从这里,两个解决方案出现:
- 不要对 non-volatile 转化造成波动;
- 定义合适的复制构造函数或复制对象成员"manually";
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
字段的访问顺序,从而避免了这个问题。
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.
从这里,两个解决方案出现:
- 不要对 non-volatile 转化造成波动;
- 定义合适的复制构造函数或复制对象成员"manually";
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
字段的访问顺序,从而避免了这个问题。