2014-09-08 13 views
6

Ho una progettazione che richiede che i valori siano contenuti in determinati bit all'interno di una parola a 32 bit. L'esempio dei bit 10-15 deve contenere il valore 9, con tutti i bit rimanenti pari a 0. Quindi, per semplicità/leggibilità, ho creato una struttura che contiene una versione suddivisa di ciò che viene richiesto.Digitare struct to integer C++

struct { 
    int part1 : 10; 
    int part2 : 6; 
    int part3 : 16; 
} word; 

posso quindi impostare part2 ad essere uguale a qualsiasi valore è richiesto, e impostare le altre parti come 0.

word.part1 = 0; 
word.part2 = 9; 
word.part3 = 0; 

Ora voglio prendere quella struct, e convertirlo in un unico Numero intero a 32 bit. Lo faccio compilando forzando il casting, ma non sembra un modo molto elegante o sicuro di convertire i dati.

int x = *reinterpret_cast<int*>(&word); 

Se provo a lanciarlo proprio come un normale reinterpret_cast<int>(word) ottengo il seguente errore:

invalid cast from type 'ClassName::<anonymous struct>' to type 'int' 

Ci deve essere un modo migliore di fare questo, non riesco proprio a capirlo. Grazie in anticipo!

Nota: deve essere fatto in C++ fusione stile, a causa delle norme e quant'altro ... occhio rotolo

+1

Sì, ora che non lavoro più per IBM, userei solo un sindacato. (Non si può menzionare la parola U in IBM, lo sai). –

+3

Nota che non è definito dove quei bitfield si trovano all'interno di 'int', ma solo il numero di bit che essi prendono. –

+0

@HotLicks Sì, non è IBM, ma è sicuramente un luogo che ha una vista simile :) – MZimmerman6

risposta

5
union Ints { 
    struct { 
    int part1 : 10; 
    int part2 : 6; 
    int part3 : 16; 
} word; 
uint32_t another_way_to_access_word; 
}; 

può aiutare

+0

Ricordo vagamente che ci sono alcune parole dure nello standard che i sindacati possono avere "comportamenti non documentati", ma quanto sopra dovrebbe funzionare con qualsiasi compilatore ragionevole. –

+0

@HotLicks: c'è una formulazione da donnola, ma a nessuno importa. –

+0

@MooingDuck: la gente ha assunto questo atteggiamento nei confronti di comportamenti non definiti nel passato. Quindi un aggiornamento del compilatore ha trasformato il loro codice "dovrebbe funzionare con qualsiasi compilatore ragionevole" in buchi di sicurezza. –

3

Il tentativo reinterpret_cast<int>(word) non funziona perché non c'è conversione operatore definito tra il tipo di struct definito dall'utente e int.

Si potrebbe aggiungere un operatore di conversione al vostro struct, o, preferibilmente, IMHO una funzione chiamata per eseguire la conversione, ad esempio:

struct { 
    uint32_t part1 : 10; 
    uint32_t part2 : 6; 
    uint32_t part3 : 16; 

    uint32_t get_all_parts() const 
    { 
     return (part1 << 22) + (part2 << 16) + part3; 
    } 
} word; 

nota, ho usato unsigned int come un comportamento su spostamento a sinistra hanno ben definito .

+0

Funzionerebbe anche, ma stavo cercando qualcosa che non dovessi scrivere piccole sottofunzioni come il codice 'get_all_parts' b/c, questo deve essere fatto molte volte. I miei valori sono in realtà non scritti nel codice effettivo (non semplificato), ma l'ho rimosso per semplicità – MZimmerman6

+1

quindi aggiungere un operatore di conversione. –

3
typedef struct word { 
    uint32_t part1 : 10; 
    uint32_t part2 : 6; 
    uint32_t part3 : 16; 

    operator int(){ 
    return (part1 << 22) + (part2 << 16) + part3; 
    } 

    struct word operator=(int i){ 
    this->set(i); 
    return *this; 
    } 

    void set(int i){ 
    part1 = (0xFFFF0000 & i) >> 16; 
    part2 = (0x0000FC00 & i) >> 10; 
    part3 = (0x000003FF & i); 
    } 

    word(int i){ 
    this->set(i); 
    } 
} word; 

Che dovrebbe farlo.

struct word myword = 20; 
struct word second_word(50); 

myword = 10; 
second_word.set(50); 

int x = myword; 
iny y = second_word; 

Nota: l'ho provato. Compila perfettamente. E funziona perfettamente.