【发布时间】:2019-06-03 11:58:27
【问题描述】:
假设我有一个 32 位硬件寄存器 Reg,我希望能够以 32 位值(例如 Reg = 0x12345678)或位域(例如 Reg.lsw = 0xABCD)的形式访问它。我可以通过声明一个带有匿名结构成员的联合,以及向/从uint32_t 声明赋值和转换运算符来实现这一点。在 little-endian 环境中,代码可能如下所示:
#include <cstdint>
#include <cstdio>
typedef union
{
uint32_t val ;
struct
{
uint32_t lsw : 16 ;
uint32_t msw : 16 ;
} ;
operator = (uint32_t n) { val = n ; }
operator uint32_t() const { return val ; }
} HWR ;
int main()
{
HWR Reg ;
Reg = 0x12345678 ;
Reg.lsw = 0xABCD ;
printf ("%X\n", uint32_t(Reg)) ;
}
但是现在假设我有一大堆这样的寄存器,每个都有自己的位域布局,并且我有一个头文件FieldDefs.h,将这些位域布局声明为命名结构。如何在上述代码中使用这些命名结构,以便访问 32 位值以及各个位域?我可以这样做:
#include "FieldDefs.h" // Defines struct MyHWR
typedef union
{
uint32_t val ;
struct MyHWR field ;
operator = (uint32_t n) { val = n ; }
operator uint32_t() const { return val ; }
} MyHWRUnion ;
但现在我需要输入 Reg.field.lsw =... 而不是 Reg.lsw =...
有没有办法(在 C++17 中)将已定义的结构声明为联合的匿名成员?如果重要的话,我正在使用 g++ 版本 7.3.0。
【问题讨论】:
-
当我再次查看问题定义和我的答案时,我觉得我有点过于复杂了。
Reg.val访问是界面的一部分吗? -
@R2RT:好问题!在我的代码 sn-p 中,它不必是;但我也发现自己想做
Reg.val &= 0xFF之类的事情,这需要val才能访问。我想我可以写Reg = uint32_t(Reg) & 0xFF。 -
好的,那么我的代码甚至可以简化为在不暴露
val的旧g++s 中工作。将其添加到答案中
标签: c++ c++17 anonymous-class