論理値の型について

[戻る]
紅' 2007/12/26(水) 23:58:59
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 への変換は !!(論理値) が便利

ものすごく基本的な事柄でお恥ずかしい限りなのですが、ご教示いただければ幸いです。

wclrp ( 'o') 2007/12/27(木) 00:19:39
正直なところ知らない。
BOOLは言語で決められたものじゃなくてboolがなかった頃から存在したものなので
俺はBOOLをboolと同じものとは思わない。intと同じものと思っている。
個人的な感想だけどboolに変換することってあまりないから
!!を便利とは感じてなかったりする。
boolが出来るまで0か0以外だったし今でもそれは残っているし
あえてboolを使うことあまりないな。

YuO [E-Mail] 2007/12/27(木) 00:39:00
> 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が特殊だと思った
方がよいでしょう。

アキラ [HomePage] 2007/12/27(木) 08:59:25
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)
   ...

シャノン 2007/12/27(木) 10:18:16
既に出ているように、BOOL は C/C++ の言語規格にはなく、VC++ や Windows SDK が独自
に定義した型で、int の別名です。
ただし、中身が int だからといって int として扱うべきではなく、中身が 0 と それ以
外しかない真偽値として扱うべきです。
「0 とそれ以外しかない」って当たり前じゃないか、と思われるかもしれませんが、重要
なのは、値が2パターンしかないということです。1 も 2 も 2147483647 も真という同
じ値です。
とは言うものの、GetMessage みたいな腐った関数もあるわけですがorz

ちなみに、DDK には BOOLEAN という型があります。こいつは char の別名です。

アキラ [HomePage] 2007/12/27(木) 10:25:50
BOOLからboolへの変換はこうすればいいような気もします

BOOL b;
bool a = b == TRUE;

maru 2007/12/27(木) 10:37:03
> bool a = b == TRUE;
これはまずいのでは?

επιστημη [HomePage] 2007/12/27(木) 10:54:51
BOOL b;
bool a = (b != FALSE);

なんだけど、bool への変換規則は 
「0ならfalse / 0以外はみんなtrue」
だから

BOOL b;
bool a = b;

でいぃんじゃないかと。

アキラ [HomePage] 2007/12/27(木) 11:46:48
申し訳ないです。逆でした。

×
>bool a = b == TRUE;>bool a = (b != FALSE);

以下は正しいですが、VCだと警告がでます
bool a = b; // 警告:intを論理値trueかfalseに強制的に変換します

επιστημη [HomePage] 2007/12/27(木) 13:40:27
> 以下は正しいですが、VCだと警告がでます
> bool a = b; // 警告:intを論理値trueかfalseに強制的に変換します

warning-level-3以上で文句言ってきますねぃ。
bool a = (b!=0); が妥当/無難かなー

仲澤@失業者 2007/12/27(木) 15:40:46
bool a = bool( b);
で済ませてます(vv;)。ゼロ/非ゼロに分かれるようです。

紅' 2007/12/27(木) 21:41:10
みなさま、ご返信をありがとうございました。

まとめるとこんな感じでしょうか。

・共に真偽値(「論理値」から改めます)を示すはずの == と ! で
 型が違うのは 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

そうなんですよね...

紅' 2007/12/27(木) 21:41:34
[[解決]]
ごめんなさい。
またチェックを入れるのを忘れてました。

たいちう 2007/12/27(木) 21:53:02
> ・BOOL は windows.h に定義されている古い?型。
>  C/C++ で標準なのは bool 。BOOL は標準には存在しない。

Cで真偽値を扱うために広く使われているtypedefがBOOL。
Cにboolは存在しない。

と、思っているのだけど。規格とか今すぐに調べられません。
どなたか、フォロー or 駄目出しをお願いできません?

YuO [E-Mail] 2007/12/27(木) 23:26:30
> Cで真偽値を扱うために広く使われているtypedefがBOOL。
> Cにboolは存在しない。

Cでは_Bool型があります。
で,<stdbool.h>をインクルードすると,
bool, true, false, __bool_true_false_are_defined
の各マクロを定義します。

ただし,各種論理演算の結果はCにおいては_Bool型ではなくint型です。
さらに,これらはC99の新規要素なので,VC++ではまだ対応していないはずです。

Ban 2007/12/28(金) 00:39:37
> 「真偽値は 0 とそれ以外」という原則について、実際に他人のコードをみると
> これを無視した書き方が結構みられます。「(真偽値) == true」とか。

本当に "true" (小文字)だったのであれば、そして(真偽値)がbool型であれば、
C++のboolならば(不正なキャストなどしなければ)trueかfalseしかありえないので、
「(bool型の値) == true」は一概に問題がある/無視しているとは言えないです。
# とはいえ、あまりお勧めはしませんが。

一方、C言語の場合やWin32のBOOLでは、「0とそれ以外」が一般的なので、
「(BOOL型の値) == TRUE」だったら一般によくないコードだと言っていいと思います。
# もちろん、特定のケースで問題なく動くものだとしても、作法として。

CとC++は一緒に考えるべきでない/区別して考えた方がよいのでは、と思います。

紅' 2007/12/31(月) 00:32:20
返信をありがとうございます。

・ C に bool はない

 そうだったのですか(汗。
 知りませんでした。ご指摘に感謝します。

 これまで使った環境が C/C++ 両対応であったことと、基礎勉強はほとんどなしで
 実践投入だった事などもあり、このような基本的なところにまだ穴がありそうな
 気がしてきました。ちょっと調べてみます。

・ (真偽値) == true

 これまで思考の基本が BOOL だったため、== TRUE のつもりで書いていました。
 失礼しました。

 なぜか私のまわりは BOOL の真偽値にしても先のように書かないと
 気の済まない人たちばかりだったようで。「 TRUE は 1 だけど"真"は 0 以外を
 指すから危ないよ」と言っても聞き入れてくれませんでした。

 が、ご指摘のような true のつもりで TRUE を使用していたなら、勘違いはあるにしても
 ある程度は解るかもしれません。TRUE を使用している時点で間違いではあるのですが。

>CとC++は一緒に考えるべきでない/区別して考えた方がよいのでは、と思います。

 肝に銘じます。

Ban 2007/12/31(月) 01:04:31
> 気の済まない人たちばかりだったようで。「 TRUE は 1 だけど"真"は 0 以外を

ちなみに、シャノンさんも触れられていますが、
Win32でのTRUEが1なのはあくまでWin32の場合であって、
その界隈以外では「~0 / 0xFFFFFFFF / -1」等になっている場合もあります。
このあたりも歴史的経緯というか、あくまで0か!0な所以です。

紅' 2007/12/31(月) 01:20:38
あうあう。
心得ました。ご指摘、ありがとうございます。

古いスレッドには追加発言できません。