2015-02-09 10 views
20

Sto scambiando pacchetti con un dispositivo incorporato e mi piacerebbe davvero essere in grado di usare enum anche nelle parti sub-byte delle definizioni dei pacchetti. Ma non posso immaginare una sintassi che potrebbe funzionare e ho il sospetto che non è possibile, dal momento che non riesco a capire come dichiarare un sottotipo parziale byte in C++:È possibile specificare la larghezza del bit di un enum in C++ 11?

enum class communication_path_t : uint8_t { 
    Ethernet = 0, Wifi = 1 
}; 

typedef struct { 
    communication_path_t pathByte; // works, uses one byte 
    // ... 
    // single byte split three ways 
    uint8_t retryCount : 3; 
    communication_path_t path : 3; // compile error 
    uint8_t deviceType : 2; 
} packet_t; 

Ciò non compilare, perché non è possibile inserire un enum a 8 bit in un campo a 3 bit. A cura nella errore esatto:

<anonymous struct>::path’ is too small to hold all values 
    of ‘enum class MyNamespace::communication_path_t’ [-Werror] 

Quello che mi piacerebbe fare è qualcosa di simile:

enum class communication_path_t : uint8_t : 3 { ... 

o

typedef uint8_t:3 three_bit_int_t; 
enum class communication_path_t : three_bit_int_t { ... 

Nessuno di quelli di compilazione, e sto avendo problemi nel trovare documentazione che si riferisca sia a campi di bit sia a enumerazioni, facendomi sospettare che non ce ne siano. Prima di passare ore a guardare, è quello che sto cercando di fare anche possibile?


Modifica: l'aggiornamento a g ++ - 4.9 non risolve il problema. E 'notevolmente indolore, basta:

sudo apt-get install g++-4.9 
g++-4.9 --version 

g++-4.9 (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2 
GCC 4.9.2 released [2014-10-30] 

poi cambiare la mia catena di costruzione di utilizzare "g ++ - 4.9" invece di "g ++". Purtroppo ottengo lo stesso errore:

g++-4.9 -Dlinux -std=c++11 -pthread (...) ../common/LogPacketBreakdown.cpp 
In file included from ../common/LogPacketBreakdown.cpp:12:0: 
../common/PacketInfo.h:104:50: error: ‘Digiflex::<anonymous 
    struct>::communicationPath’ is too small to hold all values of 
    ‘enum class Digiflex::communication_path_t’ [-Werror] 
    communication_path_t communicationPath : 3; 

sembra che ho bisogno di 5.0 e che non è nella lista strumenti sperimentali Ubuntu quindi avrei bisogno di costruire dai sorgenti. Penso che vivrò con la soluzione alternativa per ora. Grazie a tutti per il vostro aiuto.

+3

Chi ha downvoted questo? Raramente vediamo una domanda più perfetta. – Potatoswatter

+2

... anche, kudos per usare il C++ moderno su un dispositivo embedded. – Potatoswatter

+0

Grazie. Sono abituato a Delphi quindi sembra un approccio naturale, soprattutto quando abbiamo utenti poliglotta dell'output incorporato (Delphi, C++, ObjectiveC e Java.) Per ragioni, ovviamente). È più semplice leggere il codice di tutti nel modo più simile possibile e utilizzare qualsiasi tipo di sicurezza disponibile. –

risposta

12

Il codice inviato deve essere accettato dai compilatori più recenti. Puoi vedere questo bug report dove dovrebbe essere avvenuta la correzione: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51242

Nel gcc di oggi, dovrebbe essere ancora emesso un avviso. In clang, non dovresti vedere nulla.

+1

@CodeAbominator: il primo commento include un test case che è sostanzialmente identico al tuo codice. –

+0

Interessante, il bug ha un anno ed è esattamente quello che sto cercando di fare. Lo standard dice anche "Un campo di bit deve avere un tipo di enumerazione o ** (3.9.1)." Sfortunatamente non sembra che verrà risolto in qualunque momento. –

+0

Un altro bug con maggiori informazioni dallo standard. Sembra ancora più probabile che questo dovrebbe funzionare: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56566 –

8

No, non esiste un modo per typedef un bitfield in C++, nemmeno con un tipo di enumerazione.

Bitfield-ness è una proprietà delle dichiarazioni di variabili membro, non è supportata dal sistema di tipi.

Ma il tuo primo esempio è perfetto. Come dice Bill, si tratta di un bug GCC, e come sviluppatori GCC note, è solo un avvertimento dal 2013. La soluzione alternativa è usare int path : 3; e convertire i valori di enumerazione, o non usare affatto uno enum.

+0

Grazie. Ovviamente ho temuto tanto, ma è utile averlo confermato. –

0

Funziona almeno da g ++ 4.8 su debian, quindi presumo anche su ubuntu.

Il compilatore fornisce solo un avviso, l'errore in questo caso è stato risolto da -Werror opzione del compilatore. È una buona idea configurare -Werror per overflow poiché questo verrà segnalato quando si assegna un valore enum che non si adatta a un campo bit.

Problemi correlati