I have a uint64 variable which often only requires high or low 32 bit access. I am using a 32-bit ARM Cortex M0, and to help with speed and I am trying to overlap the uint64 var
There is actually little to no reason to use a union. Instead, use shift/mask, possibly in inline
functions to extract the two halves:
static inline uint32_t upper(uint64_t val)
{ return (uint32_t)(val >> 32); }
static inline uint32_t lower(uint64_t val)
{ return (uint32_t)val; }
This will be very likely optimized by the compiler to the same code as the union-approach.
However, as you are refering to anonymous struct/union members: Omitting the name is a feature of the struct/union which includes the member, not the member being a struct/union. So you can use:
union {
uint64_t v64;
struct {
uint32_t l32;
uint32_t h32;
}; // here the name can been omitted
} my_flex_var;
Problems are:
uint64_t
.Normal usage of a volatile is to load/store it always with full size. If that is not the case, a race condition might uccur and you are in the world of locking/mutex, etc. which makes things very much more complicated. If the two fields are only loosely related, you are very likely better off with two 32 bit variables or a struct
thereof.
Typical usage:
volatile uint64_t v64;
void int_handler(void)
{
uint64_t vt = v64;
uint32_t l = lower(vt);
uint32_t h = higher(vt);
}
This ensures the variable is read only once. With a proper compiler, the assignments to l
, h
will not generate any code, but the registers with vt
are used. That depends, of course on your code, but even if there is some overhead, that will be negligible.
(Sitenote: This is from my own practise as a long time embedded programmer)