VC での論理値(BOOL/bool)の型について教えてください。
これまで私は VC&MFC でプログラムを書く事が多く、論理値 = BOOL型 と考えていました。
もちろん bool 型も知っていたのですがあまり使わず、「同じようなもの」と括っていまし
た。
が、先ほど思いついて、以下の事柄を VC6.0 & ダイアログベースのプログラムを作成して試し
てみました。
bool a;
BOOL b;
a = b; // ( 1) コンパイル時に警告が出る
a = ( 1 == 1 ); // ( 2) 警告は出ない
b = ( 1 == 1 ); // ( 3) 警告は出ない
sizeof( a ); // ( 4) = 1
sizeof( b ); // ( 5) = 4
sizeof( 1 == 1 ); // ( 6) = 4
sizeof( 1 != 1 ); // ( 7) = 4
sizeof( ( 1 == 1 ) ); // ( 8) = 4
sizeof( !( 1 == 1 ) ); // ( 9) = 1
sizeof( !!( 1 == 1 ) ); // (10) = 1
上記の (8) までは判るとして、(6) ~ (8) までと (9)、(10) とが異なるのは
それが仕様であり当然の事と理解して良いのでしょうか。
感覚的には (6) 以降はすべて論理値であるはずなので、BOOL か bool の違いはあっても
同じ型だと認識していて、疑った事がありませんでした。(汗
VC の場合、! 演算子の戻り値が bool であり、他の論理式の型は BOOL との認識は正しいで
しょうか。
一応、検索を掛けて調べたところ、以下のような記述がみられました。
・論理値としては bool を用いるべき
・BOOL(もしくは型不明) から bool への変換は !!(論理値) が便利
ものすごく基本的な事柄でお恥ずかしい限りなのですが、ご教示いただければ幸いです。
正直なところ知らない。
BOOLは言語で決められたものじゃなくてboolがなかった頃から存在したものなので
俺はBOOLをboolと同じものとは思わない。intと同じものと思っている。
個人的な感想だけどboolに変換することってあまりないから
!!を便利とは感じてなかったりする。
boolが出来るまで0か0以外だったし今でもそれは残っているし
あえてboolを使うことあまりないな。
> VC の場合、! 演算子の戻り値が bool であり、他の論理式の型は BOOL との認識は正
しいで
> しょうか。
正しくありません。
#include <windows.h>
#include <iostream>
#include <string>
#include <typeinfo>
int main ()
{
bool a = false;
BOOL b = FALSE;
std::cout << ( 4) << typeid( a ).name() << std::endl;
std::cout << ( 5) << typeid( b ).name() << std::endl;
std::cout << ( 6) << typeid( 1 == 1 ).name() << std::endl;
std::cout << ( 7) << typeid( 1 != 1 ).name() << std::endl;
std::cout << ( 8) << typeid( ( 1 == 1 ) ).name() << std::endl;
std::cout << ( 9) << typeid( !( 1 == 1 ) ).name() << std::endl;
std::cout << (10) << typeid( !!( 1 == 1 ) ).name() << std::endl;
return 0;
}
をいくつかのバージョンで実行してみました。
Visual Studio 6.0
( 4) bool
( 5) int
( 6) long
( 7) long
( 8) long
( 9) bool
(10) bool
Visual Studio.NET / Visual Studio.NET 2003 / Visual Studio 2005 / Visual C++
2008 Express Edition
( 4) bool
( 5) int
( 6) bool
( 7) bool
( 8) bool
( 9) bool
(10) bool
と,バージョンによって結果が別れました。
VC++ 6.0はなぜかlongとして認識していますが,これはBOOL,つまりはintではないの
で,別の認識になっています。
# 不思議な結果です。
どちらにしても,VS2002からはちゃんと修正されているので,VC++ 6.0が特殊だと思った
方がよいでしょう。
BOOLはintのtypedefであり、Win32API(つまりはC)やそれをラップしたMFC等で論理値が必
要な場合にBOOLを使います
VCとしてではなく、C++として考えた場合にはBOOLは使いません(言語仕様にもないです
し)
// ※ <windows.h>をインクルードしない
int main()
{
BOOL b; // エラー!BOOLなんてありません
return 0;
}
BOOL(int)からboolへは暗黙の変換があるので!!を使う必要はないはずです
(警告は出ますが)
if文もboolへの暗黙の変換があるので当然BOOLも使えます
BOOL b;
if (b)
...
if (!b)
...
既に出ているように、BOOL は C/C++ の言語規格にはなく、VC++ や Windows SDK が独自
に定義した型で、int の別名です。
ただし、中身が int だからといって int として扱うべきではなく、中身が 0 と それ以
外しかない真偽値として扱うべきです。
「0 とそれ以外しかない」って当たり前じゃないか、と思われるかもしれませんが、重要
なのは、値が2パターンしかないということです。1 も 2 も 2147483647 も真という同
じ値です。
とは言うものの、GetMessage みたいな腐った関数もあるわけですがorz
ちなみに、DDK には BOOLEAN という型があります。こいつは char の別名です。
BOOLからboolへの変換はこうすればいいような気もします
BOOL b;
bool a = b == TRUE;
> bool a = b == TRUE;
これはまずいのでは?
BOOL b;
bool a = (b != FALSE);
なんだけど、bool への変換規則は
「0ならfalse / 0以外はみんなtrue」
だから
BOOL b;
bool a = b;
でいぃんじゃないかと。
申し訳ないです。逆でした。
×
>bool a = b == TRUE;
○
>bool a = (b != FALSE);
以下は正しいですが、VCだと警告がでます
bool a = b; // 警告:intを論理値trueかfalseに強制的に変換します
> 以下は正しいですが、VCだと警告がでます
> bool a = b; // 警告:intを論理値trueかfalseに強制的に変換します
warning-level-3以上で文句言ってきますねぃ。
bool a = (b!=0); が妥当/無難かなー
bool a = bool( b);
で済ませてます(vv;)。ゼロ/非ゼロに分かれるようです。
みなさま、ご返信をありがとうございました。
まとめるとこんな感じでしょうか。
・共に真偽値(「論理値」から改めます)を示すはずの == と ! で
型が違うのは VC6 の方言。2002 以降は bool に統一されている。
・BOOL は windows.h に定義されている古い?型。
C/C++ で標準なのは bool 。BOOL は標準には存在しない。
・BOOL -> bool の変換には以下のような方法がある。
- !!(真偽値)
- ( (真偽値) != FALSE )
- ( (真偽値) != 0 )
- bool( (真偽値) )
以上からすると、移植性などを考え特に必要ない場合には BOOL ではなくて
bool を使う方が安全な気がします‥‥が。windows.h を使用する環境と
そうでない環境とで共用するライブラリ?で真偽値の型が混在してしまうと
言うのも抵抗がある‥‥。
( 私は BOOL を戻り値の型にする関数をよく書いてました orz )
YuO さんが試してくださった型チェックで VC6 の == などが long だったのには
どう反応して良いのやら。windows.h がない環境でやったらどうなるのかと
コンソールアプリで sizeof( 1 == 1 ) を試したら 4 バイトだったのに、やはり
BOOL がなかったのにはちょっと笑いましたが。long だったんですね。
あと、BOOL -> bool には、気づいた後は少し冗長ですが以下のように書いてました。
- ( (真偽値) ? true : false )
たったこれだけの事でもいろいろな表現があって面白いですね。
本題からははずれますが、頂いたご意見の中にあった、
「真偽値は 0 とそれ以外」という原則について、実際に他人のコードをみると
これを無視した書き方が結構みられます。「(真偽値) == true」とか。
私は怖くてそういう書き方は出来ないのですが、やはり気をつけようと思います。
自分以外、ほとんど全員が先の例のような書き方をするので、正直ちょっと
自信がなくなってました。
と、言うわけで取りあえず 解決 とさせて頂きます。
ありがとうございました。
>とは言うものの、GetMessage みたいな腐った関数もあるわけですがorz
そうなんですよね...
ごめんなさい。
またチェックを入れるのを忘れてました。
> ・BOOL は windows.h に定義されている古い?型。
> C/C++ で標準なのは bool 。BOOL は標準には存在しない。
Cで真偽値を扱うために広く使われているtypedefがBOOL。
Cにboolは存在しない。
と、思っているのだけど。規格とか今すぐに調べられません。
どなたか、フォロー or 駄目出しをお願いできません?
> Cで真偽値を扱うために広く使われているtypedefがBOOL。
> Cにboolは存在しない。
Cでは_Bool型があります。
で,<stdbool.h>をインクルードすると,
bool, true, false, __bool_true_false_are_defined
の各マクロを定義します。
ただし,各種論理演算の結果はCにおいては_Bool型ではなくint型です。
さらに,これらはC99の新規要素なので,VC++ではまだ対応していないはずです。