2012-06-01 13 views
5

Ich habe eine Struktur mit Bit-Feldern (insgesamt 32 Bit Breite) und ich habe eine 32-Bit-Variable. Wenn ich versuche, den Variablenwert zu meiner Struktur zuweisen, bekam ich einen Fehler:Wie weisen Sie einer Struktur mit Bitfeldern Werte zu?

error: conversion from ‘uint32_t {aka unsigned int}’ to non-scalar type ‘main()::CPUID’ requested.

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; 

Sie haben keine Ahnung, wie es in dem kürzesten Weg zu tun? Danke

P.S. Natürlich habe ich einen besseren EAX-Wert in echtem Code, aber ich nehme an, dass es hier keinen Einfluss hat.

+3

Möglicherweise möchten Sie hier eine "union" statt einer "struct". Andernfalls können Sie jede Variable in der Struktur nur separat setzen. du kannst nicht 'CPUID CPUIDoutput = EAX;' du musst 'CPUIDoutput.stepping = EAX;' – andre

Antwort

7

Sie sollten sich nie darauf verlassen, wie der Compiler Ihre Struktur im Speicher ablegt. Es gibt Möglichkeiten, mit einer einzigen Aufgabe zu tun, was Sie wollen, aber ich werde es weder empfehlen noch Ihnen sagen.

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

Und die entgegengesetzten

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

Jetzt sehe ich nur diese Art der Zuweisung für mich. – Irina

+0

@ user1430759. Dies ist die einzige sichere/tragbare Möglichkeit, dies zu tun. Mach dir keine Sorgen über die Leistung, da dies vom Compiler optimiert wird. Versuchen Sie außerdem, die Nummern vor dem Kopieren zu überprüfen, indem Sie den Code einfügen. – Shahbaz

+0

Und fühlen Sie sich frei zu stimmen und akzeptieren, wenn Sie die Antwort mochten;) – Shahbaz

1

Dies sind Strukturelemente, also müssen Sie sie direkt zuweisen oder sicherstellen, dass das RHS Ihrer Zuweisung ein Wert vom Typ CPUID ist. Nicht sicher, warum Sie erwarten, dass Sie der Struktur aus einer Ganzzahl zuweisen können.

Die Tatsache, dass die Struktur Bitfelder enthält, und dass die Summe der Bits identisch mit der Anzahl der Bits in der Ganzzahl ist, die Sie zuweisen möchten, bedeutet nichts. Sie sind immer noch keine kompatiblen Typen für Zuweisungszwecke.

Wenn dies zu vage war, sollten Sie mehr/besseren Code anzeigen.

+0

machen Ich denke, in der bearbeiteten Codeversion ist es offensichtlich, warum ich versuche, EAX der gesamten Struktur auf einmal zuzuweisen. Also, wenn ich dich richtig verstanden habe, ist es für mich nicht möglich es zu tun? Ich kann nur jedes Feld einzeln zuweisen? – Irina

2

Nur wenn somebody's interessiert, Ive got eine bessere Lösung für meine eigenen: die folgend wäre

Der beste Weg, um die Zuordnung zu tun Frage:

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

Das ist noch schlimmer als mein Vorschlag der Gewerkschaft. –

+1

@Anna, ich hoffe, Sie verwenden das nicht in echtem Code, der in realen Situationen verwendet würde. Das Problem besteht darin, dass es dem Compiler freisteht, für Optimierungszwecke Zwischenräume zwischen Mitgliedern der Struktur hinzuzufügen. Sie können sich also nicht darauf verlassen, dass Ihre Struktur und Ihre Nummer dasselbe Layout haben. Auch ohne Auffüllen wird Ihre Aussage in einem Big-Endian-Computer absolut falsch sein. – Shahbaz

3

Verwenden Sie eine Union.

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