2011-02-07 2 views
5

ビットマスクを列挙値に使用することは可能ですが、作成方法はわかりません。ビットマスクを使用した列挙値の結合

enum State 
{ 
    minimizing = 0, 
    maximizing, 

    minimized, 
    maximized 
}; 

状態が常にState.minimizedまたはState.maximizedで、サイズ変更で追加の状態を持つことができます。

私は、単純な列挙型を持っています。したがって、何かを最大化して最小化することができます

答えて

16

私はmyStateのタイプがenum Stateであると仮定します。

伝統的にはenumを使用すると、このタイプの変数で使用できる定数値を作成できます。変数myStateの組み合わせに設定する場合は、enumに定義されている値を使用します。

enumは1,2,4、および8を有効な値として定義しますが、変数を4 | 2 = 6. Cは、enumのすべてのタイプに対してintというタイプの実装を使用していますが、C++ではそうではありません。 myState = 6はC++では無効です。実際には、myState = 4はC++では有効ではありません。明示的にキャストするか、enumの定数名のいずれかを使用する必要があります。

Cでも可能ですが、myStateをそのタイプで定義されていない値(たとえば6)に設定することはお勧めしません。あなたのケースでは

、結果的には以下のようになりそうですソリューション:

typedef enum { 
    OTHER, 
    MINIMIZED, 
    MAXIMIZED 
} win_size_t; 

typedef struct { 
    win_size_t current; 
    win_size_t next; 
} state_t; 

state_t myState; 

こうすることで、あなたはフィールドundependently currentnextに書き込むことができます。

ビットフィールドを残したい場合は、構造体の要素のサイズをビット単位で設定できます。ビットフィールドの実装はコンパイラによって異なりますが、危険です。コンパイラがビットフィールドに列挙型を持つことを受け入れるかどうかはわかりません(enumintです)。

typedef struct { 
    win_size_t current : 2; // not tested 
    win_size_t next : 2; 
} state_t; 

上記の解決策はもちろん有効です。私のポイントは、変数myStateにタイプとしてenum Stateがある場合、その値にはenumのメンバーのみを使用し、組み合わせには使用しないでください。

myStateには別のタイプがあります。何を知っていますか?


myStateenum Stateタイプでない場合は、組み合わせてあなたのenumで定義された定数を使用することができます。あなたが希望する可能性はありません

myState = MAXIMIZED | MINIMIZING; 

しかし、また、物事:

enum State { 
    MINIMIZING = (1u << 0), 
    MAXIMIZING = (1u << 1), 
    MINIMIZED = (1u << 2), 
    MAXIMIZED = (1u << 3), 
}; 

unsigned int myState = 0; 

myState |= MAXIMIZED; // sets that bit 
myState &= ~MAXIMIZED; // resets that bit 

これを使用すると、1つの割り当てで2つのことを行うことができます

myState = MAXIMIZED | MINIMIZED; // does that make sense? 
+0

ありがとう!私はオプション#1に行きました。確かに、それは感知しません。 MINIMIZED'が可能であり、2つの列挙型を持つことが可読性に優れているためです。 –

+0

列挙をビットフィールドに限定することは未定義の動作であり、結果はコンパイラによって異なります。私が間違っている場合はまた、私を修正してください。 –

+0

@DavidTóthあなたは正しいと思われる、これのためにありがとう! https://stackoverflow.com/a/33590935/108802 – Gauthier

2

この効果は、列挙のすべてのフィールドを指定することで得ることができ、ビットマスク効果を得るために2の累乗で増加します。たとえば、あなたの場合:

enum State 
{ 
    minimizing = 1, 
    maximizing = 2, 

    minimized = 4, 
    maximized = 8 
}; 

したがって、(State.maximized | State.minimizing)の組み合わせを使用できます。ただし、State.maximizedまたはState.minimizedという制限は適用されません。あなたがそれをしたいのであれば、それらを1ビットに変換することができますが、この例では最大化も最小化もしない場合があると思います。

+2

通常はシフト – justin

+0

を使用して書かれていますが、どうすれば使用できますか?私のように: 'myState = minimized; if(isMaximizing){myState = maximizing} '最小化された状態を失うことなく、最大化状態を設定したい –

+0

次に、' myState | = maximizing; 'を使うことができます。これは、他のビットに触れることなく興味のあるビットを設定します。ゼロにするには、 'myState&=〜maximizing;'を使用します。比較を行うときは注意してください。 'myState == minimized'は動作しません。' myState&minimized == minimized'(または '!= 0')が必要です。私があなたの場合は、1つのフィールドが「現在の状態」で、もう1つが「次の状態」であるとみなします。 – Gauthier

12

のような、あなたの列挙のすべての値に異なるビットを使用します。次に

enum State 
{ 
    minimizing = 0x01, // 00000001 
    maximizing = 0x02, // 00000010 
    minimized = 0x04, // 00000100 
    maximized = 0x08 // 00001000 
}: 

、あなたはビット単位または(minimizing | maximized)とビット単位のAND(bool is_minimized = (flags & minimized);)との値のためのテストで複数の値を組み合わせることができます。

+2

味の質問ですが、私は ''(1u << 0) ''(1u << 1) ''(1u << 2) ''(1u << 3) 'を好む。どのビットを意味するのかがはっきりしています。 – Gauthier

+0

16進法で値を定義するのはなぜですか? 'minimizing = 1'も動作します –

+4

@NatanYellin:そうですが、もう1つの状態を追加し、10進数を使用する場合は16を書きます。2ビット、ビット4を設定したいとします。結果は10進数で18で、0x12よりも読みにくくなります(明らかでない場合は、2398の小数点にどのビットがセットされているかを確認してください)。どのビットが設定されているかに関心がある場合は、16進数を使用してください。 – Gauthier

2

私はVS2012でこれを試してみました、ビットフィールドを使用している場合、オプティマイザはビットを正しく組み合わせるように見えます。 1つの命令で両方のビットを設定

次いで
struct BITS { int x: 1; int y:1; }; 

BITS b; 
b.x = b.y = 1; 

関連する問題