2010-10-22 13 views
30

Apple talvolta utilizza l'operatore Bitwise-Shift nelle definizioni enum. Ad esempio, nel CGDirectDisplay.h file di che fa parte del core grafico:Perché utilizzare l'operatore Bitwise-Shift per i valori in una definizione C enum?

enum { 
    kCGDisplayBeginConfigurationFlag = (1 << 0), 
    kCGDisplayMovedFlag   = (1 << 1), 
    kCGDisplaySetMainFlag   = (1 << 2), 
    kCGDisplaySetModeFlag   = (1 << 3), 
    kCGDisplayAddFlag   = (1 << 4), 
    kCGDisplayRemoveFlag   = (1 << 5), 
    kCGDisplayEnabledFlag   = (1 << 8), 
    kCGDisplayDisabledFlag  = (1 << 9), 
    kCGDisplayMirrorFlag   = (1 << 10), 
    kCGDisplayUnMirrorFlag  = (1 << 11), 
    kCGDisplayDesktopShapeChangedFlag = (1 << 12) 
}; 
typedef uint32_t CGDisplayChangeSummaryFlags; 

Perché non usare semplicemente incrementando int 's come in un "normale" enum?

+1

Domanda correlata: http://stackoverflow.com/questions/2159138/c-bitwise-operator-in-enum-custom-authorization-in-mvc – Oded

+1

Rende facile vedere che l'enum è tutte le bandiere con solo un singolo set. –

+3

In realtà la vera ragione, come ha sottolineato Loki, è la leggibilità. Potresti usare 1, 2, 4, 8, 16 e così via (poteri di 2) ma corri il rischio di commettere errori mentre 1 << 0, 1 << 1, 1 << 2, 1 << 3 è più facile per digitare e leggere lasciandolo al compilatore per eseguire il calcolo del valore effettivo. Se vuoi programmare smart, devi sapere cosa può fare il compilatore per te e sfruttare le sue capacità. – Telemat

risposta

46

In questo modo è possibile aggiungere più flag contemporaneamente per creare un "set" di flag e quindi utilizzare & per scoprire se un determinato flag è presente in un set.

Non è possibile farlo se è stato utilizzato semplicemente numeri incrementali.

Esempio:

int flags = kCGDisplayMovedFlag | kCGDisplaySetMainFlag; // 6 
if(flags & kCGDisplayMovedFlag) {} // true 
if(flags & kCGDisplaySetModeFlag) {} // not true 
+0

Bene, questo spiega alcune cose per un codice C++ che sto aiutando a districare. Grazie! – CodeMouse92

2

Ciò consentirà una variabile di combinare facilmente più bandiere:

unit32_t multFlag = kCGDisplayRemoveFlag | kCGDisplayMirrorFlag | kCGDisplaySetMainFlag' 
4

Se avete Flaga = 1, FlagB = 2 e FlagC = 3, Flaga o FlagB darebbe lo stesso valore di FlagC. L'operatore di turno viene utilizzato per garantire che ogni combinazione di flag sia unica.

63

Forse scrivere i valori in formato esadecimale (o binario) aiuta :-)

enum { 
    kCGDisplayBeginConfigurationFlag = (1 << 0), /* 0b0000000000000001 */ 
    kCGDisplayMovedFlag    = (1 << 1), /* 0b0000000000000010 */ 
    kCGDisplaySetMainFlag    = (1 << 2), /* 0b0000000000000100 */ 
    kCGDisplaySetModeFlag    = (1 << 3), /* 0b0000000000001000 */ 
    kCGDisplayAddFlag     = (1 << 4), /* 0b0000000000010000 */ 
    kCGDisplayRemoveFlag    = (1 << 5), /* 0b0000000000100000 */ 
    kCGDisplayEnabledFlag    = (1 << 8), /* 0b0000000100000000 */ 
    kCGDisplayDisabledFlag   = (1 << 9), /* 0b0000001000000000 */ 
    kCGDisplayMirrorFlag    = (1 << 10),/* 0b0000010000000000 */ 
    kCGDisplayUnMirrorFlag   = (1 << 11),/* 0b0000100000000000 */ 
    kCGDisplayDesktopShapeChangedFlag = (1 << 12) /* 0b0001000000000000 */ 
}; 

Ora si possono aggiungere (o "o" loro) e ottenere valori diversi

kCGDisplayAddFlag | kCGDisplayDisabledFlag /* 0b0000001000010000 */ 
+1

Grazie mille, questo rende le cose SUPER chiare! :) –

+3

COSÌ chiaro, si potrebbe prendere in considerazione l'impostazione di questa come risposta accettata. – deed02392

+0

Quali sarebbero i limiti con questo? Ci sarebbero un massimo di, diciamo, 16 valori che puoi inserire in questo enum prima di esaurire le possibilità? – mylogon

0

.. perché 1<<7 sembra più conciso e più facile da leggere rispetto a 01000000. Non è vero?

+2

bene per me .. no – paulm

+0

Questo non risponde alla domanda – artman

-5

utilizzando #define è più comprensibile. ma enum potrebbe raggruppare questi valori insieme.

+0

Questo non risponde affatto alla domanda. – Oliver

Problemi correlati