2012-06-01 8 views
5

ビットフィールド(全部で32ビット幅)を持つ構造体を持っていて、32ビットの変数を持っています。私は構造体に変数の値を代入しようとすると、私はエラーました:ビットフィールドを持つ構造体に値を割り当てる方法は?

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; 

を使用すると、最短の方法でそれを行うにはどのように任意のアイデアを持っていますか?ありがとう

P.S.もちろん、私は実際のコードでEAXのより適切な価値を持っていますが、ここでは影響しないと思います。

+3

ここでは 'struct'ではなく' union'が必要な場合があります。それ以外の場合は、構造体内の各変数のみを個別に設定することができます。 'CPUID CPUIDoutput = EAX;'あなたは 'CPUIDoutput.stepping = EAX;'を実行しなければなりません。 – andre

答えて

7

コンパイラがどのように構造をメモリにレイアウトするかに決して頼るべきではありません。私は1つの課題であなたが望むことをする方法がありますが、私はあなたに勧告も教えもしません。

割り当てを行うための最善の方法は、次のようになります。

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

反対

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

今、私はこのような割り当て方法しか見ません。 – Irina

+0

@ user1430759これはこれを行うための唯一の安全な方法です。これはコンパイラによってすべて最適化されるため、パフォーマンスについては心配しないでください。また、コピーする前にコードを貼り付ける前に、数字を2回確認してください。 – Shahbaz

+0

あなたが答えが好きだったならば、投票して同意してください;) – Shahbaz

1

これらは構造体のメンバーなので、直接代入するか、代入のRHSがCPUIDの値であることを確認する必要があります。あなたが整数から構造体に代入できると思われる理由がわからない。

構造体にビットフィールドが含まれ、ビットの合計が割り当てようとしている整数のビット数と同じであるという事実は何も意味しません。代入目的ではまだ互換性のある型ではありません。

これがあまりにも曖昧だった場合は、より多くの/より良いコードを表示することを検討してください。

+0

私はEAXを一度に全構造体に割り当てようとしています。それで、とにかく私があなたを正しく理解すれば、私はそれをすることができません。私は各フィールドを別々に割り当てることができますか? – Irina

2

somebody's興味を持って、I'veは私自身のためのよりよい解決策を得ただけであれば質問:

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

それは私の組合提案よりもさらに悪いです。 –

+1

@Anna、実際の状況で使用される実際のコードではこれを使用しないことを願っています。問題は、最適化のために構造体のメンバー間でパディングを自由に追加できることです。したがって、同じレイアウトを持つために構造体と番号に頼ることはできません。パディングしなくても、ビッグエンディアンのマシンではステートメントが間違っています。 – Shahbaz

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; 
} 
関連する問題