使用 static_assert 验证结构和 uint32_t 的 typedef 联合中的位域
Using static_assert to verify bitfields in a typedef union of a struct and an uint32_t
我正在尝试将 static_assert 用于 FPGA 的寄存器,并定义了以下结构与位域和所有变量的联合。但是每当我尝试编译时,static_assert 都不会编译,而且我会收到一条错误消息,指出变量没有命名类型。如果我尝试转发声明,它并不能解决问题。我不确定让 static_assert 工作的正确模式是什么。对编写以下代码的正确方法有什么想法吗?
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;
}
运行:
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;
^~~~~
Any ideas of the correct way to write the following code?
没有正确的方法。无法使用 static_assert
检查位域是否在特定位置。
您正在使用 C++。不要使用工会。编写一个带有访问器的普通 class,访问器使用掩码访问特定位 - 这种方式清晰、可移植且保证工作。或者使用 std::bitset
.
在 C++20 中,您可以使用 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(只有 msvc 有 std::bit_cast
)。
请注意,位域确实是特定于实现的(考虑字节顺序),并且 static_assert
可能通过或不通过取决于 compilers/architecture/...
不要使用位域,使用老式的位掩码
namespace FpgaRegister
{
constexpr uint32_t do_it = 1 << 0;
constexpr uint32_t fault = 1 << 1;
constexpr uint32_t all = do_it | fault;
}
static_assert(FpgaRegister::all == 0x3, "Not equal");
我正在尝试将 static_assert 用于 FPGA 的寄存器,并定义了以下结构与位域和所有变量的联合。但是每当我尝试编译时,static_assert 都不会编译,而且我会收到一条错误消息,指出变量没有命名类型。如果我尝试转发声明,它并不能解决问题。我不确定让 static_assert 工作的正确模式是什么。对编写以下代码的正确方法有什么想法吗?
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;
}
运行:
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;
^~~~~
Any ideas of the correct way to write the following code?
没有正确的方法。无法使用 static_assert
检查位域是否在特定位置。
您正在使用 C++。不要使用工会。编写一个带有访问器的普通 class,访问器使用掩码访问特定位 - 这种方式清晰、可移植且保证工作。或者使用 std::bitset
.
在 C++20 中,您可以使用 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(只有 msvc 有 std::bit_cast
)。
请注意,位域确实是特定于实现的(考虑字节顺序),并且 static_assert
可能通过或不通过取决于 compilers/architecture/...
不要使用位域,使用老式的位掩码
namespace FpgaRegister
{
constexpr uint32_t do_it = 1 << 0;
constexpr uint32_t fault = 1 << 1;
constexpr uint32_t all = do_it | fault;
}
static_assert(FpgaRegister::all == 0x3, "Not equal");