While working with low-level C++ for bare-metal embedded systems (STM32), I came across a use case for an "anonymous union member" declaration with non trivial (a struct) type. Is such a thing possible ?
I have tried the following kind of code :
struct Specialization_CR1_t
{
uint32_t a :1 ;
uint32_t :31;
};
struct CR1_t
{
union
{
struct
{
uint32_t : 1;
uint32_t b: 1;
uint32_t :30;
} ;
// Few tries...
// Specialization_CR1_t {};
// Specialization_CR1_t;
Specialization_CR1_t () ;
// Fails with "expected unqualified-id before ')'"
};
};
int main()
{
//The goal :
struct CR1_t CR1;
CR1.a = 1;
CR1.b = 0;
}
The goal is to avoid having CR1.<thing>.a
. Obviously, there is the possibility to directly declare Specialization_CR1_t
anonymously in the union
, however the ultimate goal is to be able to use a template and tmpl_CR1_t
instead of "just" Specialization_CR1_t
.
I am aware of the potential memory issues with the stuff displayed here. However, since this is in bare-metal embedded environment, the memory structure is fully known, the bits are packed well and tight and the tool-chain is fixed (no issues with bitfields).
Moreover, since this structure will be directly mapped in memory, I cannot afford the overhead of another variable. The total size of my structure have to be 32 bits and writing into a
or b
have to change only the correct bit.
Best regards !
ISO C11 allows anonymous structs inside other struct/unions. This is supported as an extension by some C++ compilers, including GNU-compatible (g++, clang++), and by MSVC++. The GCC manual has some examples.
This is AFAIK not allowed in ISO C++. If you're using a compiler that doesn't implement this extension, see the middle part of this answer.
I'm pretty sure the anonymous union is a red herring here, and you'd have exactly the same problem trying to declare b
as a 32-bit object with 31 bits of padding and 1 value-bit using that anonymous-struct in any other context.
If it was legal inside an anonymous union, it would be legal anywhere. (But instead it's not, and is legal nowhere in ISO C. As @Peter points out in comments, the name Instance
in struct {<members>} Instance
can't be omitted. And if you make it struct foo {<members>};
you'd just be declaring a type, not an instance.)
You'll probably just have to write a class with operator=
and operator bool
overloads, which you can do because this is C++.
(Consider retitling the question with what you're actually trying to do: write an anonymous struct with a bitfield member.)
Or if you want help with the wrapper class, take a step back from the X-Y problem where the anonymous-struct approach has apparently hit a dead end (unless there is some compiler-specific support for it) and ask a new question about writing a convenient wrapper that exposes a single bit in a word as an integer type. With vendor headers, compiler extensions, or plain or C++ operator overloads.
Although given how you're using the union, you can do this to get what you want, at least without templates, right?
struct CR1bits
{
uint32_t a: 1;
uint32_t b: 1;
uint32_t :30;
};
So maybe you should be asking something about how you can template this to what, have different type names that have some subset of the named bits? Maybe the C preprocessor can help with that, in a more clunky way that still lets the code using these types look the way you want.
GNU C++, and MSVC, both support anonymous structs. This compiles and works:
union Obj {
struct { // extension: anonymous struct
int x;
int y;
int z;
};
int elems[3];
};
a->x
or a->elems[0]
both access the same object (assuming standard struct layout with no padding).
And apparently this is standard ISO C11.