Search code examples
c++structvolatile

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;
}

This won't compile, because struct FOO test = foo; generates an error:

error: binding reference of type 'const FOO&' to 'volatile FOO' discards qualifiers

How can I copy a volatile struct into another struct in C++ (before C++11)?

Many people suggested to just delelte volatile, but I can't do that in that case, because I want to copy the current SPI-Reg setttings inside a µC and this is declared volatile by the manufacturer headers. I want to copy those settings, because the manufactuerer also provides an Library to use the SPI for EnDat-Communication, and I don't have access to the source-code. Since I have to change the SPI-Reg-Settings during runtime I want to easyly get back to the library SPI-settings without calling the init_endat()-lib fkt again (it's unspecified what happens if i call it twice).

Could I possibly use memcopy() for that?

As suggested, this is a copy of the following question.

Why am I not provided with a default copy constructor from a volatile?


Solution

  • 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;
    }