Volatile Struct = Struct Not Possible, Why

volatile struct = struct not possible, why?

This is ill-formed because FOO has an implicit copy constructor defined as:

FOO(FOO const&);

And you write FOO test = foo; with foo of type volatile FOO, invoking:

FOO(volatile FOO const&);

But references-to-volatile to references-to-non-volatile implicit conversion is ill-formed.

From here, two solutions emerge:

  1. don't make volatile to non-volatile conversions;
  2. define a suited copy constructor or copy the object members "manually";
  3. const_cast can remove the volatile qualifier, but this is undefined behavior to use that if your underlying object is effectively volatile.

Could I possibly use memcopy() for that?

No you cannot, memcpy is incompatible with volatile objects: thre is no overload of it which takes pointers-to-volatile, and there is nothing you can do without invoking undefined behavior.

So, as a conclusion, your best shot if you cannot add a constructor to FOO is to define:

FOO FOO_copy(FOO volatile const& other)
{
FOO result;
result.a = other.a;
result.b = other.b;
result.c = other.c;
return result;
}

Or with C++11's 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 Struct Semantics

In your example, the two are the same. But the issues revolve around pointers.

First off, volatile uint8_t *foo; tells the compiler the memory being pointed to is volatile. If you want to mark the pointer itself as volatile, you would need to do uint8_t * volatile foo;

And that is where you get to the main differences between marking the struct as volatile vs marking individual fields. If you had:

typedef struct
{
uint8_t *field;
} foo;

volatile foo f;

That would act like:

typedef struct
{
uint8_t * volatile field;
} foo;

and not like:

typedef struct
{
volatile uint8_t *field;
} foo;

Does making a struct volatile make all its members volatile?

Another question can be asked (or simply another way to look at the original question):

Does making a struct const make all its members const?

If I have:

struct whatever { int data; };

const whatever test;

Will test.data be const too?

My answer is : Yes. If you declare an object of type whatever with const then all its members will be const too

Similarly, if you declare an object of type whatever with volatile then all its members will be volatile too, just like if you declare the object with const, all it's member will be const too.

const and volatile are two faces of the same coin; they're so that the Standard often refers to them as cv-qualifiers.


Quoting from the Standard ($7.1.5.1/8)

[Note: volatile is a hint to the
implementation
to avoid aggressive
optimization involving the object
because the value of the object might
be changed by means undetectable by an
implementation. See 1.9 for detailed
semantics. In general, the semantics
of volatile are intended to be the
same in C + + as they are in C. ]

That means, if your object is an instance of a struct, then the compiler cannot avoid aggressive optimization involving the object, unless it avoids aggressive optimization of each of it's members. (Otherwise, how else it can avoid optimization involving the object?)


Related topic:

Why do we use volatile keyword in C++?

indexing an element from a volatile struct doesn't work in C++

Your program is trying to copy a SensorData_t object. The compiler supplies a copy constructor with the following signature:

SensorData_t(const SensorData_t &)

This copy constructor will not work with volatile arguments, hence the compilation error.

You can write your own copy constructor which works with volatile SensorData_t objects (as well as non-volatile SensorData_t objects):

struct SensorData_t {
SensorData_t() = default;

SensorData_t(const volatile SensorData_t &other)
: test(other.test) {
}

int test;
};

Passing a pointer to a struct with a volatile member as a function argument

Short answer: No need to add volatile on hdlPtr.

Long Answer: Unless the hdlPtr can be changed in some unexpected way, there is no need to declare it volatile. Given that it's being local to the function, it can not be changed by anything other than the uartInitialize. Given that you declared it 'const', it can not be changes by the uartInitialize itself.

How can I make a volatile struct behave exactly like a volatile int during assignment?

Your initial problem is because the implicit assignment operator has signature

Bar& operator=(const Bar& rhs);

... and that isn't callable for a volatile object. The warnings are because your updated function returns a volatile reference, but that reference is never used. GCC thinks that this might be a problem. The simplest way to fix this is to change the return type to void!

There is another problem: Your function will call itself in an infinite recursion. I suggest the following:

struct Bar {
int a;
Bar& operator=(const Bar&rhs) = default;
void operator=(const volatile Bar& rhs) volatile // Note void return.
{
// Caution: This const_cast removes the volatile from
// the reference. This may lose the point of the original
// volatile qualification.
//
// If this is a problem, use "a = rhs.a;" instead - but this
// obviously doesn't generalize so well.
const_cast<Bar&>(*this) = const_cast<const Bar&>(rhs);
}
};

volatile Bar vbar;
Bar bar;

int main(){
vbar = bar; // All four combinations work.
bar = vbar;
vbar = vbar;
bar = bar;
return 0;
}

This means you won't be able to chain assignment operators when using volatile structs. I assert this is not a huge loss.

Final aside: Why are you using volatile - it's not very useful for multi-threaded code (it is useful for memory mapped IO).

In C, how do you declare the members of a structure as volatile?

Exactly the same as non-struct fields:

#include <stdio.h>
int main (int c, char *v[]) {
struct _a {
int a1;
volatile int a2;
int a3;
} a;
a.a1 = 1;
a.a2 = 2;
a.a3 = 3;
return 0;
}

You can mark the entire struct as volatile by using "volatile struct _a {...}" but the method above is for individual fields.



Related Topics



Leave a reply



Submit