ビット演算に関してです。
C/C++でやっています。
ビット演算を用いて Windows API の CreateWindow関数に ウィンドウスタイルを渡すような感覚で
できたらなぁと思い、チャレンジしてみました。
しかしなぜかうまくいきません。
やったことは
- enumで(ビット演算用)定数定義
C++
1enum TEST_ENUM{ 2 TEST_DEFALUT = 0, 3 TEST_ENUM_TYPE1 = 1, 4 TEST_ENUM_TYPE2 = 2, 5 ... 6 TEST_ENUM_TYPE100 = 6 7}; 8
のように1~6 と デフォルトの 0 を定義します。
- unsigned int flag を引数として持つ関数 func に設定しながら渡す
C++
1// 定義部 2void func( unsigned int flag ){ 3 4 if( flag & TEST_ENUM_TYPE1 ) cout << "TEST_ENUM_TYPE1が定義されている" << endl; 5 6 if( flag & TEST_ENUM_TYPE2 ) cout << "TEST_ENUM_TYPE2が定義されている" << endl; 7 8 // 上記のやつを TEST_ENUM_TYPE6ぐらいまで。 9return; 10} 11 12// main関数等の呼び出し側 13func( TEST_ENUM_TYPE1 | TEST_ENUM_TYPE4 | TEST_ENUM_TYPE3 ); 14
としました。
これを動かしてみると、
TEST_ENUM_TYPE1が定義されている TEST_ENUM_TYPE2が定義されている TEST_ENUM_TYPE3が定義されている TEST_ENUM_TYPE4が定義されている ...
と立てていないフラグまで "立った" ことにされています。
なぜなのでしょうか?
Windows API だと 普通にできるのに...
順番がある?
でも CreateWindowに順番を逆にしても ( もちろん 一つの引数として ) 普通に想定した動きになります。
何がいけないのでしょうか?
もし
C++
1if( flag & TEST_ENUM_TYPE1 ){ 2 cout << "TEST_ENUM_TYPE1が定義されている" << endl; 3}else if( flag & TEST_ENUM_TYPE2 ){ 4 cout << "TEST_ENUM_TYPE2が定義されている" << endl; 5}else if( flag & TEST_ENUM_TYPE3 ){ 6 cout << "TEST_ENUM_TYPE3が定義されている" << endl; 7}else if( ,,, 8... 9}else{ // フラグは"全く"立っていない 10 cout << "フラグなし" << endl; 11}
とする方法もありそうですが、これフラグ用定数が2つしかなくても 2通り ( 個別 ) + 4通り ( 組み合わせ ) だし、
3つ以上だと 1個だで設定されている場合, 2個設定されている場合, 3個設定... とそれの和になるだろうし...
分離するだけでも 100行以上ありそう...
これを 一番最初にやった方法みたいにできたらいいのですが...
( そうすれば パターンは考えなくても良さそうだし。 ただ 組み合わせで 切り替えする場合は別として。 )
どのようにやればいいのでしょうか。
「C言語 ビット演算」 ( C++版も同様 ) のように検索かけたり、「C言語 ビット演算 Windows API」みたいに検索しても
演算そのもの ( "&" でチェック, "|" で追加, "~" で削除 etc. ) しか載っていない場合が多いし。
つまり、パターン ( 一個だけ設定されたとき, 二個設定されたとき, 三個設定されたとき...また それぞれの組み合わせ ) を考えなくても
if( flag & 定数 )
みたいにすれば いいみたいな方法です。
もうちょっと調べてみると
がヒットしました。
上記サイトはC#ですが、シフト演算子というのでしょうか。
"<<" を使って定義しています。
なので
1 を基準にして、1以降は 1に n 分( ぶん ) シフトしてやると
C++
1enum TEST_ENUM{ 2 TEST_DEFALUT = 0, 3 TEST_ENUM_TYPE1 = 1, 4 TEST_ENUM_TYPE2 = 1 << 1, 5 TEST_ENUM_TYPE3 = 1 << 2, 6 TEST_ENUM_TYPE4 = 1 << 3, 7 TEST_ENUM_TYPE5 = 1 << 4, 8 ... 9};
としたところ、処理自体はうまくいきました。
また
ロベールのC++教室
の「先ずは基本から」-> 「第49章 ビットでフラグ」でも大体同様のやり方。
( 後者は マクロ定数にしていますが。 )
しかし、上記 enumに「TEST_ENUM_TYPE101 = 1 << 100」を追加しようとすると
(ファイルパス+ファイル名):(行):(列?): warning: left shift count >= width of type [- shift-count-overflow] ...
とコンパイルエラー。
int ( 厳密には unsigned intですが。 ) なので 100 は 範囲内だと思うのですが...
もしかして こういうビット演算用定数 は 何十 ( 大体 30前後? ) までしかできないのでしょうか?
もし可能なら ファイル ( ディレクトリ を含んでもいいですが。 ) を列挙する関数 ( あるいはクラス? )を作成して、
「JPGファイル, BMPファイル, PNGファイル, GIFファイル ... を列挙対象にする」みたいに できるのですが...
拡張子は私が聞いたことがある ( よく使う ) ものだけでも 100ぐらいありそうですし。
( そこまではいかなくても、使える範囲が広がるし。 )
知りたいことは、簡単に言えば、
「パターンを考えずに抽出&処理をし、また定数の個数が100や1000でも耐えうるビット演算方法」
です。
[情報]
言語 : C/C++
WinAPI : あり ( ただ、今回はあまり関係ないかも... )
コンパイラ: MinGW ( 同上 )
宜しくお願い致します。
回答6件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。