2014-09-08 33 views
6

Mam projekt, który wymaga wartości zawartych w niektórych bitach wewnątrz 32-bitowego słowa. Przykład bity 10-15 musi zawierać wartość 9, a pozostałe bity to 0. Dla uproszczenia/czytelności utworzyłem strukturę, która zawiera zepsutą wersję tego, co jest zadawane.Wpisz casting struct na liczbę całkowitą C++

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

mogę następnie ustawić part2 być równa co wartość jest wymagana, i ustawić inne części jako 0.

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

I teraz chce podjąć tego struct i przekształcić go w pojedynczym 32-bitowa liczba całkowita. Mam to skompilowanie przez wymuszenie odlewania, ale nie wydaje się to bardzo eleganckim lub bezpiecznym sposobem konwertowania danych.

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

Gdy próbuję rzucić go tak, jak normalny reinterpret_cast<int>(word) pojawia się następujący błąd:

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

Musi istnieć lepszy sposób to zrobić, po prostu nie mogę zrozumieć. Z góry dziękuję!

Uwaga: Musi być wykonane w języku C++ odlewania stylu, ponieważ standardy i etażerka ... oko rolka

+1

Tak, teraz, gdy już nie pracuję dla IBM, po prostu użyję związku. (Nie można wspomnieć o słowie U w IBM, wiesz.) –

+3

Należy zauważyć, że nie jest zdefiniowane, gdzie te pola bitowe znajdują się wewnątrz 'int', tylko liczba bitów, które biorą. –

+0

@HotLicks Tak, to nie jest IBM, ale zdecydowanie miejsce, które ma podobne poglądy :) – MZimmerman6

Odpowiedz

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

może pomóc

+0

Niejasno przypominam sobie, że w standardzie istnieje słowo "łasica", że związki mogą mieć "nieudokumentowane zachowanie", ale powyższe powinno działać z każdym rozsądnym kompilatorem. –

+0

@HotLicks: Jest takie słownictwo, ale nikogo to nie obchodzi. –

+0

@MooingDuck: Ludzie przyjęli takie podejście do niezdefiniowanych zachowań w przeszłości. Następnie uaktualnienie kompilatora zmieniło ich kod "powinien działać z jakimkolwiek sensownym kompilatorem" w luki w zabezpieczeniach. –

3

Próba reinterpret_cast<int>(word) nie działa, ponieważ nie ma konwersji operator zdefiniowany między typem struktury zdefiniowanym przez użytkownika a int.

Można dodać operator konwersji do swojej struktury, a najlepiej IMHO nazwanego funkcję zrobić konwersję, np:

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; 

Uwaga, użyłem niepodpisanych ints jak mają dobrze określone zachowanie na lewym przesunięcia .

+0

To też by działało, ale szukałem czegoś, czego nie musiałem pisać małych podfunkcji, jak twój 'get_all_parts' kod b/c, to musi być zrobione wiele razy. Moje wartości są faktycznie unsigned ints w faktycznym (nie uproszczony) kod, ale usunąłem to dla prostoty sake – MZimmerman6

+1

, więc dodaj operator konwersji zamiast. –

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; 

To powinno wystarczyć.

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

myword = 10; 
second_word.set(50); 

int x = myword; 
iny y = second_word; 

Uwaga: Testowałem to. Kompiluje się idealnie. I działa idealnie.

Powiązane problemy