如何使用位字段为结构赋值?

时间:2012-06-01 13:40:17

标签: c++ bit-fields

我有一个带有位字段的结构(总共32位宽度),我有一个32位变量。当我尝试将变量值赋给我的struct时,我收到一个错误:

  

错误:从'uint32_t {aka unsigned int}'转换为非标量类型'main():: CPUID'请求。

struct CPUIDregs
    {
       uint32_t EAXBuf;
    };
CPUIDregs CPUIDregsoutput;   


int main () {

 struct CPUID          
    {
          uint32_t   Stepping         : 4;         
          uint32_t   Model            : 4;        
          uint32_t   FamilyID         : 4;        
          uint32_t   Type             : 2;        
          uint32_t   Reserved1        : 2;         
          uint32_t   ExtendedModel    : 4;         
          uint32_t   ExtendedFamilyID : 8;          
          uint32_t   Reserved2        : 4;          
    };

    CPUID CPUIDoutput = CPUIDregsoutput.EAXBuf;

你知道如何以最短的方式做到这一点吗?感谢

P.S。当然我在实际代码中有更合适的EAX值,但我想这不会影响到这里。

4 个答案:

答案 0 :(得分:8)

您永远不应该依赖编译器如何在内存中布局您的结构。有一些方法可以通过单一作业完成您想要的任务,但我既不会推荐也不会告诉您。

完成作业的最佳方式如下:

static inline void to_id(struct CPUid *id, uint32_t value)
{
    id->Stepping         = value & 0xf;
    id->Model            = value >> 4 & 0xf;
    id->FamilyID         = value >> 8 & 0xf;
    id->Type             = value >> 12 & 0x3;
    id->Reserved1        = value >> 14 & 0x3;
    id->ExtendedModel    = value >> 16 & 0xf;
    id->ExtendedFamilyID = value >> 20 & 0xff;
    id->Reserved2        = value >> 28 & 0xf;
}

相反的

static inline uint32_t from_id(struct CPUid *id)
{
    return id->Stepping
         | id->Model << 4
         | id->FamilyID << 8
         | id->Type << 12
         | id->Reserved1 << 14
         | id->ExtendedModel << 16
         | id->ExtendedFamilyID << 20
         | id->Reserved2 << 28;
}

答案 1 :(得分:3)

使用联盟。

union foo {
    struct {
        uint8_t a : 4;
        uint8_t b : 4;
        uint8_t c : 4;
        uint8_t d : 4;
        uint16_t e;
    };
    uint32_t allfields;
};

int main(void) {
    union foo a;

    a.allfields = 0;
    a.b = 3;

    return 0;
}

答案 2 :(得分:2)

如果有人感兴趣,我已经为自己的问题找到了更好的解决方案:

*(reinterpret_cast<uint32_t *> (&CPUIDoutput)) = CPUIDregsoutput.EAXBuf;

答案 3 :(得分:1)

这些是struct成员,因此您需要直接指定它们,或者确保赋值的RHS是CPUID类型的值。不确定为什么你希望能够从整数分配给结构。

结构包含位域的事实,以及位的总和恰好与您尝试分配的整数中的位数相同,没有任何意义。出于分配目的,它们仍然是不兼容的类型。

如果这太模糊,请考虑显示更多/更好的代码。