如果我有:
__PRE__会
struct whatever {
int data;
};
volatile whatever test;不稳定? 我有一个指向某些易失性内存的指针,我试图取消引用该内存并将其复制到该结构的非限定副本(反之亦然)。存储器的格式由第三方结构定义指定。在 C 中,我可以取消引用内存,一切都很好。然而,C++抱怨它找不到合适的赋值运算符(clang的错误在这里比gcc清楚得多:候选函数(隐式复制赋值运算符)不可行:'this'参数具有类型'易失性vec',但方法是未标记为易失性)。此方法对于简单类型(例如整数)非常有效,但对于结构则失败。
在这种特殊情况下,所指向的值在读取对象期间不能更改,但我必须防止它们在读取过程中被缓存。
我发现我可以添加从易失性 T 到 T 的隐式转换吗?这给了我很多尝试的选择,但是我无法找到让它真正发挥作用的魔力。我怀疑所有这些解决方案都会失败,因为为什么不能使用非成员函数来重载赋值运算符?这将导致我的第三方定义的结构没有合适的结构,因为结构定义是第三方的,但这是理论上的,因为我什至无法让手动指定的成员函数完全工作(也许我可以创建一个包装结构有明确的东西吗?)。
下面的示例在 C 中编译并运行,但在 C++ 中失败。不幸的是,更完整的问题还有其他方面迫使 C++ 这样做。让它发挥作用的魔力是什么?
#include <stdio.h>
#include <stdint.h>
struct __attribute__((__packed__)) vec {
uint32_t addr;
uint32_t len:24;
uint8_t id;
};
struct vec first = { .addr=0xfeedface, .len=10, .id=5};
volatile struct vec vvector;
int main(int argc, char **argv, char **envp)
{
struct vec cvector;
volatile struct vec *pvector = &vvector;
*pvector = first;
cvector = *pvector;
printf("%x %d %d %d\n", cvector.addr, cvector.len, cvector.id, sizeof(cvector)); …Run Code Online (Sandbox Code Playgroud) (与这个问题有关,抛弃挥发物是否安全?,但不完全相同,因为该问题与特定实例有关)
是否有过在那里虚掷的情况下volatile是不被认为是危险的做法?
(一个特定的例子:如果声明了一个函数
void foo(long *pl);
Run Code Online (Sandbox Code Playgroud)
我必须实施
void bar(volatile long *pl);
Run Code Online (Sandbox Code Playgroud)
有()我需要执行栏的一部分来调用foo(PL),然后好像我不能得到这个作为是工作,因为假设由foo的编制()和bar的调用者的编辑制作()不兼容.)
作为推论,如果我有一个volatile变量v,我想打电话给foo(&v)别人的功能void foo(long *pl),那人告诉我这是安全的,我可以调用之前投的指针,我的直觉是要告诉他们,他们错了,因为没有办法保证,void foo(volatile long *pl)如果他们想支持使用volatile变量,他们应该更改声明.我们哪一个是正确的?
我有一个struct需要声明一些实例的实例,volatile因为它们代表与驱动程序共享的内存(即,该内存可能会被我的C ++程序外部的进程更改)。该struct也需要平凡的,可复制的,因为我会用一些代码,要求所有的投入是平凡的,可复制来分享它的实例。这两个要求似乎意味着我不可能安全地为volatile实例分配新的值struct。
这是我要执行的操作的简化示例:
struct foo {
uint16_t a;
uint16_t b;
};
int main() {
static_assert(std::is_trivially_copyable<foo>::value, "Oh no!");
volatile foo vfoo;
foo foo_value{10, 20};
vfoo = foo_value;
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试使用g ++进行编译,则它会vfoo = foo_value与“错误:将'volatile foo'传递为'this'参数而丢弃限定符”一起失败。根据这个问题,那是因为隐式定义的赋值运算符未声明为volatile,而我需要定义一个volatile拷贝赋值运算符才能分配给volatile对象。但是,如果我这样做:
struct foo {
uint16_t a;
uint16_t b;
volatile foo& operator=(const foo& f) volatile {
if(this != &f) {
a = f.a;
b = f.b;
}
return *this;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,静态断言将失败,因为foo如果具有用户定义的赋值运算符,则该静态断言将不再是普通复制的。
由于编译器显然已决定不允许我执行此非常简单的操作,因此我目前正在使用以下解决方法:
int …Run Code Online (Sandbox Code Playgroud)