true/falseは、1/0と保障されている?

[戻る]
しん 2005/04/08(金) 14:56:46
組み込み型boolの変域であるtrue/falseは、言語仕様で1/0に展開されると解釈して良い
のでしょうか?あるコードを見たら、

void f( bool b )
{
  assert( b==true || b==false );

  int  a[] = { 値A, 値B };

  a[ b ] を使って処理;
}

のような記述がありました。もしbの変域が[0,1]である事が保障されないなら、このよう
なコードは書けません。そこで確認させて頂いた次第です。ちなみに、VC++7.1の場合、
[0,1]になりました。

以上、宜しくお願い致します。

Ban 2005/04/08(金) 15:02:50
日本工業標準調査会(http://www.jisc.go.jp/)サイトで
JIS X3014 を検索すると言語規格が参照できます。

これの、4.1 かな。標準変換のルールが載ってます。

επιστημη 2005/04/08(金) 15:04:08
C++言語仕様では、boolはintに変換でき、false→0/true→1 となっています。

--- ISO/IEC FDIS 14882:1998(E)  ---

  4.5 - Integral promotions [conv.prom]
  ...
  -4- An rvalue of type bool can be converted to an rvalue of type int, 
      with false becoming zero and true becoming one.

Ban 2005/04/08(金) 15:08:33
失礼。4.5 でした。

# ついでに補足:先のサイトの「JIS検索」から「X3014」と入力。

Ban 2005/04/08(金) 15:09:40
# επιστημη さんとかぶりました.....orz

REE 2005/04/08(金) 15:15:22
>assert( b==true || b==false );

余談ですが、このアサートは無意味かも

Ban 2005/04/08(金) 15:36:56
> 余談ですが、このアサートは無意味かも

C++ ならそうですね。
C++ の規格とか関係なく、提示コードは歴史的な経緯でそうなっているだけなのかも。

元は C 言語でこんなのだったとか。
typedef int bool;
const bool true  = 1;
const bool false = 0;

tetrapod 2005/04/08(金) 15:40:34
むっちゃ御意。
「条件としての真」は必ずしも1でないわけで。

if (isupper(c)==true) は (必ずしも) 成立しません。

しん 2005/04/08(金) 16:34:59
[[解決]]
>JIS X3014 を検索すると言語規格が参照できます。
有難うございます。今後は、まずこれを参照させて頂きます。

>C++言語仕様では、boolはintに変換でき、false→0/true→1 となっています。
最高に簡潔明瞭な回答、有難うございます。これで安心です。

>余談ですが、このアサートは無意味かも
実は意味があります。true/false以外が格納されている事もあり得る為です。例えば バ
ッファオーバーランによる書き込みなどをした場合です。コード例では、
bool b;
memset( &b, 2, sizeof(b) );
とやると、見事にbには2が入ってしまっています(VC++7.1)。このような例を検出する為
の物です。

>元は C 言語でこんなのだったとか。
鋭い読みですね。今回は残念乍外れですが、感動しました。

>「条件としての真」は必ずしも1でない
え、そうなのですか?C++では ==等の比較系演算子の評価結果値は、bool型になると思っ
てました。いやぁ、又新たな知識が得られました。有難うございます。

という事で解決とさせて頂きます。みなさん、どうも有難うございました。

tetrapod 2005/04/08(金) 16:51:58
なにか誤解があるようなので念のため。

> C++では ==等の比較系演算子の評価結果値は、bool型になると思ってました。
この命題は真です。演算子定義も bool operator==(...) とします。

>「条件としての真」は必ずしも1でない
の意味するところは if (2) { /*then*/ } で then が実行されるということです。
マニュアル見れば記述がありますが isupper() は
・大文字でないとき 0 を返し
・大文字であるとき「非0値」を返します。
非0値つまり1とは限らない、ということです。

bool b=isupper(c); と記述した場合は、コンパイラは
・isupper(c) が 0 を返したとき b=false
・isupper(c) が非0値を返したとき b=true
にするコードを吐きます。 (4.12 boolean conversions)

isupper(c)==true の場合は true が1に変換されるので
isupper(c)==1 となりますが、これが真になるのは isupper(c) が1を返す場合のみです。
大文字のときに isupper() が返す非0値が 2 や 3 や -1 であるような処理系では
isupper(c)==true は成立しません。

επιστημη 2005/04/11(月) 11:40:38
> 例えば バッファオーバーランによる書き込みなどをした場合です。
> コード例では、
> bool b;
> memset( &b, 2, sizeof(b) );
> とやると、見事にbには2が入ってしまっています(VC++7.1)。
> このような例を検出する為の物です。

こんなのを疑ってたらキリがないぞ。

void f(double x) {
  assert( /* ここに何と書くのよ? */ );
  ...
}

しん 2005/04/11(月) 15:29:00
>isupper() は非0値つまり1とは限らない、ということ
なるほど、了解です。

>こんなのを疑ってたらキリがないぞ。
その通り。が、私は極力この類の検査をやっています。何故なら、確かに効果があるから
です。

>assert( /* ここに何と書くのよ? */ );
boolと同じです。「その値が正規の変域にあるか否かを検査」します。具体的には、
浮動小数値なら、+/-∞(Inf)や、不定値(Ind)でない事を必ず検査します。それに加え各
値毎の変域の検査をする、という具合です。例えばsin()の戻値を引数に受け取るなら、
[-1,1]である事を検査します。

# 実際には、assert対象のデータ毎に 専用のassertマクロ関数群(一種のライブラリ)
# を用意し、次回以降に少労力で済むようにしています。

世の中 何でもそうだと思いますが、「100%は無理でも、それに近づく努力をするの
が大切かな?」と思っている為、そうしています。少投資で大利益が得られると考えてい
るのも、行ってる理由の一つです。

もっと良い検出方法があれば、是非教えて下さい!

επιστημη 2005/04/11(月) 16:34:26
>「100%は無理でも、それに近づく努力をするのが大切かな?」

それにはまったくもって同意します。
が、「このboolはひょっとしたらtrueでもfalseでもないかも知れない」
と疑うのはどうよ? と考えちゃったわけで。 うーむ……

# ま、assertですからリリース時には影も形もなくなるんだから
# 目くじら立てるよなことではないのでしょうけど。

しん 2005/04/11(月) 18:24:22
>疑うのはどうよ? と考えちゃったわけで。 うーむ……
たしかにー。私の職場では、assert()やVERIFY()を使いまくるおかげで チーム内で発生
したバグの多くを撃退できるんです、恐ろしい事に。私は「呼ばれる側」の担当なのです
が、渡される値がもうメチャクチャ。既述のboolの件も実話なんですよ〜!その経験か
ら、癖で使い続けてる訳です。

>リリース時には影も形もなくなるんだから目くじら立てるよなことではない
そうですね。assert()に注力したが為に、本体がショボいんじゃ本末転倒ですものね。
ただ、私の職場環境では必須なんです。でも、いい社会勉強になりましたよ!

επιστημη 2005/04/12(火) 10:23:12
> 私の職場では、assert()やVERIFY()を使いまくるおかげで チーム内で発生
> したバグの多くを撃退できるんです、恐ろしい事に。
> その経験から、癖で使い続けてる訳です。

いや、これは推奨されるスタイルじゃねぇですか。
DbC(Design by contract)のpre-conditionに相当するわけだから。

しん 2005/04/12(火) 10:58:30
>DbC(Design by contract)のpre-conditionに相当する
まあ難しい話は良く分かりませんが、「極端にアサーション検出をする人なんだな」と思
って下さい。

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