[英]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.