C/C++で整数をブール値として評価する場合、負の数は真ですか、それとも偽ですか?コンパイラに関係なく、常に真/偽ですか?
ゼロ以外の値はすべてtrue
に、ゼロ値はfalse
に変換されます。負の数がゼロ以外の場合、それらはtrue
に変換されます。
C++ 11標準(強調鉱山)から引用:
4.12ブール変換[conv.bool]
1算術のprvalue、対象範囲外の列挙、ポインター、またはメンバー型へのポインターは、bool型のprvalueに変換できます。 ゼロ値、NULLポインター値、またはNULLメンバーポインター値は
false
に変換されます。他の値はtrue
に変換されます。 stdタイプのprvalue :: nullptr_tは、bool型のprvalueに変換できます。結果の値はfalseです。
コンパイラに関係なく、常に真/偽ですか?
コンパイラが標準に準拠している場合、または少なくとも標準のこの特定の部分に準拠している場合にのみ、上記の保証が得られます。実際には、すべてのコンパイラにこの標準的な動作があるため、心配する必要はほとんどありません。
これをコンパイルして自分でテストできます:
#include <stdio.h>
int main(int argc, char** argv) {
if (-1) {
printf("-1 is true\n");
} else {
printf("-1 is false\n");
}
return 0;
}
結果:
$ gcc -Wall -pedantic test.c -o test-c
$ g ++ -Wall -pedantic test.c -o test-cpp
$ ./test-c
-1はtrue
$ ./test-cpp
-1はtrue
もちろん、質問の2番目の部分である「コンパイラに関係なく、常に真/偽ですか?」ただし、一般に、危険な操作を行うとコンパイラは警告を表示します。上記の出力から、 "pedantic"であっても warnings 、gcc
はこのコードが完全であると見なされますいいよ.
簡単な答え:負の値、および一般的なゼロ以外の値は、条件として使用される場合にtrueとして扱われます。
Cには、式が条件として扱われる多くのコンテキストがあります。条件は、必ずしもbool
または__Bool
_型ではありません。このタイプは、1999年の標準によって言語に追加されただけです。
これらのコンテキストの中で最も明白なのは、if
ステートメントの式ですが、他の例もあります:while
、_do-while
_、for
ヘッダーの2番目の式、_?:
_条件演算子の最初のオペランド、 _!
_、_&&
_、および_||
_演算子のオペランド。 (私はと考えますこれは完全なリストですが、確かではありません。)
以下は、C標準がif
ステートメントの動作について述べていることです(「2つの形式」はif
句の有無にかかわらずelse
を指します)。
どちらの形式でも、式が0と等しくない場合、最初のサブステートメントが実行されます。
つまり、これは:
_if (foo) ...
_
これと同等です:
_if ((foo) != 0) ...
_
(演算子の優先順位の問題を回避するために、余分な括弧を追加します)。 foo
がint
型の場合、意味は明確です。 foo
が浮動小数点型の場合、_0
_は同じ型に変換されます(値が負のゼロまたはNaNである場合、微妙な問題が発生する可能性があります)。 foo
がポインターの場合、_0
_はNULLポインター定数として扱われます。 if (ptr)
はif (ptr != NULL)
と同等です(NULL
の定義が見えると仮定します)。
C++の場合、ルールの記述は少し異なりますが、効果は同じです。 C++ if
ステートメント内の条件は、タイプbool
に変換されます(Cとは異なり、タイプbool
は初期の歴史からC++に組み込まれています)。スカラー型の値からbool
への変換は、C++標準によって次のように定義されています。
ゼロ値、nullポインター値、またはnullメンバーポインター値はfalse;に変換されます。他の値はすべてtrueに変換されます。タイプstd :: nullptr_tのprvalueは、タイプbool;のprvalueに変換できます。結果の値はfalseです。
したがって、CとC++の両方で、任意のスカラー(つまり、整数、浮動小数点、またはポインター)値を条件として使用でき、スカラーがゼロに等しい場合は条件は偽、ゼロに等しくない場合は条件は真です。 Cは、これを_0
_との不等比較として定義します。 C++ではbool
への変換として定義されていますが、結果は同じです。
これは質問のトピックから少し外れていますが、真の条件として扱われる値は必ずしもtrue
とequalとは限らないことに注意することが重要です。 true
(Cの_1
_で、_#include <stdbool.h>
_があり、C++のbool
型の一意の値である場合)は、条件で使用されたときに「真理」を持つ多くの値の1つにすぎません。これが、あなたがほとんど書くべきではない理由です:
_if (cond == true) ...
_
cまたはC++のいずれか(その1つの値と実際に比較する必要がある場合を除く)。書くだけ:
_if (cond) ...
_
C++の例:
_#include <iostream>
int main() {
int n = 2;
if (n) std::cout << "n has truthiness\n";
else std::cout << "n does not have truthiness\n";
if (n == true) std::cout << "n == true\n";
else std::cout << "n != true\n";
}
_
出力は次のとおりです。
_n has truthiness
n != true
_
0
以外のものはすべてtrue
に変換されます(Cの場合は1)zero
値はfalse
(に変換されますCの場合は)。 [〜#〜] c [〜#〜]に関して C99ドラフト標準 セクション6.3.1.2
ブール型 =パラグラフ1のコメント:
スカラー値が_Boolに変換されるとき、値が0と等しい場合、結果は0です。それ以外の場合、結果は1です。
完全を期すために、セクション7.16
ブール型と値パラグラフ2を見てみると:
The macro
bool
expands to _Bool.
C++に関して C++標準案 セクション4.12
ブール変換パラグラフ1 says(- エンファシスマイン):
算術のprvalue、スコープのない列挙、ポインター、またはメンバー型へのポインターは、bool型のprvalueに変換できます。 ゼロ値、nullポインター値、またはnullメンバーポインター値はfalseに変換されます。他の値はすべてtrueに変換されます。[...]
これは、使用するコンパイラに関係なく保持されるはずです。