簡體   English   中英

如何為具有位域的結構賦值?

[英]How to assign value to a struct with bit-fields?

我有一個帶有位域(總共 32 位寬度)的結構,並且我有一個 32 位變量。 當我嘗試將變量值分配給我的結構時,出現錯誤:

錯誤:請求從“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;

你知道如何以最短的方式做到這一點嗎? 謝謝

PS當然我在實際代碼中有更合適的EAX值,但我想它不會影響這里。

您永遠不應該依賴編譯器如何在內存中布局您的結構。 有一些方法可以通過單一作業完成您想要的任務,但我既不會推薦也不會告訴您。

完成任務的最佳方式如下:

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;
}

使用工會。

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;
}

如果有人感興趣,我有一個更好的解決方案來解決我自己的問題:

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

這些是struct成員,因此您需要直接指定它們,或者確保賦值的RHS是CPUID類型的值。 不確定為什么您希望能夠從整數分配給結構。

結構包含位域的事實,以及位的總和恰好與您嘗試分配的整數中的位數相同,沒有任何意義。 它們仍然是不兼容的類型,用於分配目的。

如果這太模糊,請考慮顯示更多/更好的代碼。

我想在這里添加一些東西,以防有人需要這些信息。 正如 Shahbaz 所指出的,有一種方法可以安全地做到這一點。 這是我看到的其他問題。

聯合存在字節序問題。 當您將 uint32_t 值分配給位域時,大端將以一種順序存儲您的位,而小端將以相反的順序存儲您的位字節。 當您認為您正在為其分配一個值時,您可能會將錯誤的值分配給錯誤的位。 因此,這不是可移植的代碼。

當您更改賦值 LHS 上任何內容的指針類型時,假設您做錯了什么。 這是我的口頭禪。 當然,它有效,在這里。 同樣,這取決於字節序,以及編譯器設置和 memory 分配。 我可以將 memory 的任何塊重新映射到不同的結構中,但是如果我這樣做,那么如何確保這兩個結構具有相同的大小和順序? 如果您決定優化您的代碼並制作一個 uint16_t,或者重新排序結構上的位怎么辦? 這是一個維護噩夢。 只是……不要這樣做。 如果不是為了你自己,那么對於下一個必須維護你的代碼的人來說。

希望這有助於解釋一些完成工作但不是完成工作的方法的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM