2008年10月6日月曜日

ビットフィールドの初期化


#include <stdio.h>

class Test{
private:
char m_val: 1;
public:
Test() : m_val( 1 ) {}
bool isTrue() const { return (m_val == 1); }
void setFlag( bool flag ) { m_val = flag ? 1 : 0; }
};

int main()
{
Test t; printf("%s\n", t.isTrue() ? "true" : "false" );
t.setFlag( false );
printf("%s\n", t.isTrue() ? "true" : "false" );
return 0;
}


という風なプログラムを書いたところ、結果が
false
false
となった。
コンストラクタでビットフィールドの初期化は出来ないのかな?
たしかにこんな使い方見たこと無いけど。

追記:
char を unsigned charにしたところ、実行結果が
true
false
となった。
 コンストラクタとかまったく関係のないビットフィールドの仕様。
勉強不足が目立つ。

5 件のコメント:

匿名 さんのコメント...

msdnのマニュアルによると、ビットフィールドは基本的に符号なし、つまりunsignedの変数しか使うなってことらしい。

コンパイラのエラーチェック厳しくしたら、エラーで出るんじゃないか?

su さんのコメント...

警告レベルを最大にしてみたが、警告されなかったVC2005

char val: 1;
省略
if ( val == -1 ) 省略

とかでsignedでも-1ならtrueになるみたい。
感覚的にはわかるが、なかなか気持ち悪いね。

匿名 さんのコメント...

調べたところによると、
//return (m_val == 1);
このときに、m_valがintにキャストされてるらしい。

符号付きの場合は、増えたbitは全部1で埋められるらしいから、11111111になる。てことは、負の数は2の補数で表わすから、-1になる→falseになる。

符号なしの場合は、増えたbitは全部0で埋められるらしいから、00000001になる。てことは、そのまんま1→trueになる。

ビットフィールド使うときは、比較する時にもう一個比較用の変数用意して、
if (hoge.a == hoge.b)
みたいな感じにしろってmsdnには書いてるね。

めんどうだから、unsigned使えばいいんじゃないかな?

su さんのコメント...

おーなるほど、そんな計算になってるのね。

結局めんどうだからビットフィールドやめてboolとかにしちゃったよ\(^o^)/
1bitから4Byteへ!

su さんのコメント...

bool
4byteだと思ってたら1Byteだった。
intと一緒とかかと思ってたよ。