2015-04-22 9 views
8

Esiste qualche "buona pratica" o l'abitudine di utilizzare le variabili firmate rispetto alle variabili non firmate per le bandiere? Personalmente userò la variabile unsigned, ma posso vedere anche la variabile firmata usata per i flag in qualche codice. Intendo soprattutto nell'interfaccia della biblioteca dove conta.Utilizzo di variabili firmate vs non firmate per flag in C++

UDPATE Non riesco ad accettare la risposta "usa Enum", perché è implementation dependent e questo non può essere utilizzato nell'interfaccia della libreria.

+0

bandiere implica per me che dovrebbe essere un enum .. – Nim

+0

Vuoi dire per i set di flag di bit? O solo una singola bandiera? In quest'ultimo caso, userei un 'bool'. –

+3

@Nim - per me, flag non è un enum - perché i flag possono essere usati con operatori bit a bit come '|', '&' e '~'. – tmp

risposta

0

E 'noto che le bandiere sono sempre interi non negativi, ma perché si userebbe int/unsigned int/short/unsigned short per una bandiera? Utilizzare #define o, ancora meglio, il tipo enum.

enum flags 
{ 
    FLAG0 = 0, 
    FLAG1 = 1, 
    FLAG2 = 2, 
    ... 
    FLAGN = n 
}; 
+4

No, non usare '# define'. – user2079303

+3

si prega di leggere il commento dell'utente2079303 un'altra volta, in effetti leggerlo quante volte è necessario per mantenerlo. E applicalo, ampiamente. –

+0

'# define' può essere utile nel file di intestazione se si hanno piccoli flag (ad esempio 2 o 3) e' enum' è come abbattere una porta aperta in questa situazione. Anche se, nei progetti più grandi, suggerisco di usare sempre enum. –

3

Penso che un tipo senza segno sia una rappresentazione migliore di un insieme di flag. Dato che hai bisogno di una quantità specifica di bit equivalenti per rappresentare le tue bandiere. In un tipo firmato il primo bit è un po 'speciale.

Probabilmente il std::bitset potrebbe anche soddisfare le vostre esigenze. E ti servirà con gli operatori logici di base e i metodi di conversione.

#include <iostream> 
#include <bitset> 
using namespace std; 

int main() { 
    std::bitset<4> flags; 
    flags.set(1); 
    flags.set(3); 
    std::cout << flags.to_string() << std::endl; 
    std::cout << flags.to_ulong() << std::endl; 
    return 0; 
} 

DEMO

+2

E per coloro che sono troppo pigri per seguire il link: ci sono sovraccarichi per "&", "|", "^" e persino "[]". – TobiMcNamobi

0

Se si decide di utilizzare enum per le vostre bandiere, ecco un utile macro che crea il codice per gli operatori bit a bit per il tipo enum.

#define GENERATE_ENUM_FLAG_OPERATORS(enumType) \ 
    inline enumType operator| (enumType lhs, enumType rhs) \ 
    { \ 
     return static_cast<enumType>(static_cast<int>(lhs) | static_cast<int>(rhs)); \ 
    } \ 
    inline enumType& operator|= (enumType& lhs, const enumType& rhs) \ 
    { \ 
     lhs = static_cast<enumType>(static_cast<int>(lhs) | static_cast<int>(rhs)); \ 
     return lhs; \ 
    } \ 
    inline enumType operator& (enumType lhs, enumType rhs) \ 
    { \ 
     return static_cast<enumType>(static_cast<int>(lhs) & static_cast<int>(rhs)); \ 
    } \ 
    inline enumType& operator&= (enumType& lhs, const enumType& rhs) \ 
    { \ 
     lhs = static_cast<enumType>(static_cast<int>(lhs) & static_cast<int>(rhs)); \ 
     return lhs; \ 
    } \ 
    inline enumType operator~ (const enumType& rhs) \ 
    { \ 
     return static_cast<enumType>(~static_cast<int>(rhs)); \ 
    } 

Usage:

enum Test 
{ 
    TEST_1 = 0x1, 
    TEST_2 = 0x2, 
    TEST_3 = 0x4, 
}; 
GENERATE_ENUM_FLAG_OPERATORS(Test); 

Test one = TEST_1; 
Test two = TEST_2; 

Test three = one | two; 
+0

Preferisco usare 'std :: underlying_type :: type' invece di int. – lisyarus

+0

erm, 'auto three = Test (TEST_1 | TEST_2)' funziona bene anche con gli operatori predefiniti ... – Nim

+0

Io lavoro con un compilatore C++ 03, quindi il mio codice non include la sintassi C++ 11 :) – rozina

Problemi correlati