Ho un set di bit di bit che vengono utilizzati in un programma che sto eseguendo il porting da C a C++.Perché il C++ supporta l'assegnazione esadecimale, ma manca l'assegnazione binaria? Quanto è meglio conservare le bandiere?
Per cominciare ...
Le bandiere nel mio programma precedentemente definiti come:
/* Define feature flags for this DCD file */
#define DCD_IS_CHARMM 0x01
#define DCD_HAS_4DIMS 0x02
#define DCD_HAS_EXTRA_BLOCK 0x04
... Ora ho capito che # definisce per le costanti (contro le costanti di classe, ecc) sono generalmente considerati cattivi.
Questo solleva domande sul modo migliore per archiviare i bit flag in C++ e perché C++ non supporta l'assegnazione di testo binario a un int, come se fosse possibile assegnare numeri esadecimali in questo modo (tramite "0x"). Queste domande sono riassunte alla fine di questo post.
ho potuto vedere una soluzione semplice è quello di creare semplicemente costanti individuali:
namespace DCD {
const unsigned int IS_CHARMM = 1;
const unsigned int HAS_4DIMS = 2;
const unsigned int HAS_EXTRA_BLOCK = 4;
};
Chiamiamo questa idea 1.
Un'altra idea che avevo era di utilizzare un enum intero:
namespace DCD {
enum e_Feature_Flags {
IS_CHARMM = 1,
HAS_4DIMS = 2,
HAS_EXTRA_BLOCK = 8
};
};
Ma una cosa che mi preoccupa di questo è che è meno intuitivo quando si tratta di valori più alti, sembra ... cioè
namespace DCD {
enum e_Feature_Flags {
IS_CHARMM = 1,
HAS_4DIMS = 2,
HAS_EXTRA_BLOCK = 8,
NEW_FLAG = 16,
NEW_FLAG_2 = 32,
NEW_FLAG_3 = 64,
NEW_FLAG_4 = 128
};
};
Chiamiamo questa opzione approccio 2.
Sto pensando di utilizzare la soluzione macro di Tom Torf:
#define B8(x) ((int) B8_(0x##x))
#define B8_(x) \
(((x) & 0xF0000000) >(28 - 7) \
| ((x) & 0x0F000000) >(24 - 6) \
| ((x) & 0x00F00000) >(20 - 5) \
| ((x) & 0x000F0000) >(16 - 4) \
| ((x) & 0x0000F000) >(12 - 3) \
| ((x) & 0x00000F00) >(8 - 2) \
| ((x) & 0x000000F0) >(4 - 1) \
| ((x) & 0x0000000F) >(0 - 0))
convertito inline funzioni, per esempio
#include <iostream>
#include <string>
....
/* TAKEN FROM THE C++ LITE FAQ [39.2]... */
class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};
inline double convertToUI(std::string const& s)
{
std::istringstream i(s);
unsigned int x;
if (!(i >> x))
throw BadConversion("convertToUI(\"" + s + "\")");
return x;
}
/** END CODE **/
inline unsigned int B8(std::string x) {
unsigned int my_val = convertToUI(x.insert(0,"0x").c_str());
return ((my_val) & 0xF0000000) >(28 - 7) |
((my_val) & 0x0F000000) >(24 - 6) |
((my_val) & 0x00F00000) >(20 - 5) |
((my_val) & 0x000F0000) >(16 - 4) |
((my_val) & 0x0000F000) >(12 - 3) |
((my_val) & 0x00000F00) >(8 - 2) |
((my_val) & 0x000000F0) >(4 - 1) |
((my_val) & 0x0000000F) >(0 - 0);
}
namespace DCD {
enum e_Feature_Flags {
IS_CHARMM = B8("00000001"),
HAS_4DIMS = B8("00000010"),
HAS_EXTRA_BLOCK = B8("00000100"),
NEW_FLAG = B8("00001000"),
NEW_FLAG_2 = B8("00010000"),
NEW_FLAG_3 = B8("00100000"),
NEW_FLAG_4 = B8("01000000")
};
};
È pazzesco? O sembra più intuitivo? Chiamiamo questa scelta 3.
Quindi, per ricapitolare, le mie domande onnicomprensiva sono:
1. perché non C++ supportano un "0b" flag di valore, simile a "0x"?
2. Quale è lo stile migliore per definire le bandiere ...
i. Costanti avvolte nello spazio dei nomi.
ii. Lo spazio dei nomi ha avvolto enum di unsigned non assegnati direttamente.
iii. Spazio dei nomi avvolto in enum di interi non firmati assegnati usando una stringa binaria leggibile.
Grazie in anticipo! E per favore non chiudere questo thread come soggettivo, perché voglio davvero ottenere aiuto su quale sia lo stile migliore e perché C++ non sia costruito in capacità di assegnazione binaria.
EDIT 1
Un po 'di informazioni aggiuntive. Leggerò un bitfield a 32 bit da un file e poi lo testerò con questi flag. Quindi tienilo a mente quando pubblichi suggerimenti.
Significa "inline unsigned int bit (n) {1 << (n);}' giusto? ;) –
@ Jason: No; gli inizializzatori dell'enumeratore devono essere espressioni costanti; non è possibile chiamare una funzione in un'espressione costante, quindi deve essere una macro. –
hrmm ... Immagino che sia un buon momento per usare una macro? –