I have a pointer to some volatile memory that I am trying to dereference and copy to a unqualified copy of that structure (and vise-versa). The format of the memory is specified by a third party structure definition. In C, I can dereference the memory and all is well. However, C++ complains that it can't find a suitable assignment operator (clang's error is much clearer than gcc here: candidate function (the implicit copy assignment operator) not viable: 'this' argument has type 'volatile vec', but method is not marked volatile). This method works great for simple types (e.g. ints) but fails for structures.
In this particular case, the values being pointed to cannot change during the read of the object, but I must prevent them from being cached from read to read.
I found Can I add an implicit conversion from a volatile T to a T? which gave me a bunch of options to try, however I was unable to find the magic which will let this actually work. I suspect that all of these solutions would fail due to Why cannot a non-member function be used for overloading the assignment operator? which will cause my third-party-defined structure to not have a suitable since the structure definition is third-part, but that is theoretical since I can't even get manually specified member functions to fully work (maybe I could create a wrapper structure with something explicit?).
The example below compiles and works in C, but fails in C++. Unfortunately there are other aspects of the fuller problem which force C++. What is the magic to let this work?
#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));
}
Trying to hide the magic in extern C (my translation of a comment suggestion) didn't seem to work--still complained about discarded qualifiers and ambiguous overloads. Still works fine when using C.
extern "C" {
static void vucopy(volatile struct vec *lhs, struct vec *rhs) { *lhs = *rhs; }
static void uvcopy(struct vec *lhs, volatile struct vec *rhs) { *lhs = *rhs; }
}
...
vucopy(pvector, &first);
uvcopy(&cvector, pvector);
extern "C"
to do anything here: it affects the mangling of names and (officially) the calling convention of functions, but it doesn’t mean “the following is C”. – Turbofanstd::memcpy()
. – Nertavolatile
are deprecated in C++. The semantics ofvolatile struct
andvolatile
bit fields is unclear. Perhaps you should think of an alternative approach. – Melodymeloidvolatile
structure via C functions, and call those C functions from your C++ code? – Ovoid