我想从32位寄存器读取第2,第5和第6位。我决定使用struct位字段来存储它们。以下数据结构是否正确?
struct readData
{
int unwanted:1;
int reqbit1:1;
int unwanted1:2;
int reqbit2:2;
int unwanted2:26;
};
我不确定如何创建位字段。我将使用一个API,它将把h / w寄存器中的字节直接复制到这个结构中。在那种情况下,reqbit1会包含第二位吗?根据我的理解,编译器将第一位分配给一个int变量,第二位分配给另一个int变量,因此reqbit1将不会从寄存器中读取任何数据。以下联盟不适合这种情况吗?
union readData
{
struct readBits
{
bool unwanted:1;
bool reqbit1:1;
xxx unwanted1:2;
short reqbit2:2;
xxx unwanted2:26;
};
int regValue;
};
如果这是对的,我应该将不想要的东西声明为什么?
答案 0 :(得分:2)
通常使用以下联合:
union readData {
struct {
unsigned int unwanted:1;
unsigned int reqbit1:1;
unsigned int unwanted1:2;
unsigned int reqbit2:2;
unsigned int unwanted2:26;
} readBits;
unsigned int regValue;
};
编辑:
用法是:
#define REG_ADDRESS 0x12345678 // e.g.
union readData* rd = (union readData*)REG_ADDRESS;
char bit2 = rd->readBits.reqbit1;
char bits56 = rd->readBits.reqbit2;
答案 1 :(得分:2)
为什么不使用sizeof()
并检查分配给每个struct成员的字节数?
结构成员alignment can be found out here
为什么要将 h / w 寄存器复制到结构中然后处理结构位?可能存在使用新值更新 h / w 寄存器但结构仍未更新的情况。
如果要读取第2位,第5位和第6位,可以通过以下方式实现:
#define myregister ((unsigned long*)address of register)
unsigned long ret=0;
ret = myregister & (1<<2);
if(ret)
{ ... }
ret = myregister & (1<<5);
if(ret)
{ ... } //... and so on
恕我直言,亲吻(保持简单,愚蠢)。
答案 2 :(得分:2)
从C标准:“单位内的位域分配顺序(高阶到低阶或低阶到高阶)是实现定义的。”
所以你不应该使用秩序很重要的位域。
使用显式屏蔽和转换:
reqbit1 = (w >> 1) & 1;
reqbit2 = (w >> 4) & 3;
或
reqbit1 = (w & 0x00000002) >> 1;
reqbit2 = (w & 0x00000010) >> 4;
和另一个方向
w = (reqbit1 << 1) | (reqbit2 << 4);
“不受欢迎”的部分通常被命名为reserved1
,依此类推。