Search code examples
c++typedefunionsbit-fieldsstatic-assert

Using static_assert to verify bitfields in a typedef union of a struct and an uint32_t


I am trying to use static_assert for registers for a FPGA and defined the following unions of struct with bitfields and all variable. But whenever I try to compile static_assert won't compile and I get an error saying the variable doesn't name a type. If I try to forward declare, it doesn't solve the problem. I'm not sure what the right pattern is to get the static_assert to work. Any ideas of the correct way to write the following code?

so.h:

#include <stdint.h>

#define t_f2bits_addr (0x0000)

typedef union {
    struct {
        uint32_t do_it : 1;
        uint32_t fault : 1;
    } field;
    uint32_t all;
} t_f2bits_type;
#define t_f2bits_ptr (*(volatile t_f2bits_type *)t_f2bits_addr)

t_f2bits_type myVar; 
myVar.field.do_it = 0x1;
myVar.field.fault = 0x1;
static_assert(myVar.all == 0x3, "Not equal");

so.c

#include "so.h"

int main() 
{
    return 0;
}

run:

g++ so.c
In file included from so.c:1:0:
so.h:15:1: error: ‘myVar’ does not name a type
 myVar.field.do_it = 0x1;
 ^~~~~
so.h:16:1: error: ‘myVar’ does not name a type
 myVar.field.fault = 0x1;
 ^~~~~
so.h:17:1: error: non-constant condition for static assertion
 static_assert(myVar.all == 0x3, "Not equal");
 ^~~~~~~~~~~~~
so.h:17:1: error: the value of ‘myVar’ is not usable in a constant expression
so.h:14:15: note: ‘myVar’ was not declared ‘constexpr’
 t_f2bits_type myVar;
               ^~~~~

Solution

  • In C++20, you might use std::bit_cast:

    struct field {
        uint32_t do_it : 1;
        uint32_t fault : 1;
    };
    constexpr field myVar = [](){
        field myVar;
        myVar.do_it = 0x1;
        myVar.fault = 0x1;
        return myVar;
    }();
    static_assert(std::bit_cast<uint32_t>(myVar) == 0x3, "Not equal");
    

    Demo (only msvc has std::bit_cast there).

    Notice that bitfield is really implementation specific (think about endianess), and the static_assert might pass or not depending of compilers/architecture/...