web-dev-qa-db-ja.com

C / C ++で負の数はfalseを返しますか?

C/C++で整数をブール値として評価する場合、負の数は真ですか、それとも偽ですか?コンパイラに関係なく、常に真/偽ですか?

47
Jason Maldonado

ゼロ以外の値はすべてtrueに、ゼロ値はfalseに変換されます。負の数がゼロ以外の場合、それらはtrueに変換されます。

C++ 11標準(強調鉱山)から引用:

4.12ブール変換[conv.bool]

1算術のprvalue、対象範囲外の列挙、ポインター、またはメンバー型へのポインターは、bool型のprvalueに変換できます。 ゼロ値、NULLポインター値、またはNULLメンバーポインター値はfalseに変換されます。他の値はtrueに変換されます。 stdタイプのprvalue :: nullptr_tは、bool型のprvalueに変換できます。結果の値はfalseです。


コンパイラに関係なく、常に真/偽ですか?

コンパイラが標準に準拠している場合、または少なくとも標準のこの特定の部分に準拠している場合にのみ、上記の保証が得られます。実際には、すべてのコンパイラにこの標準的な動作があるため、心配する必要はほとんどありません。

60
Mark Garcia

これをコンパイルして自分でテストできます:

#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"であっても warningsgccはこのコードが完全であると見なされますいいよ.

7
Brendan Long

簡単な答え:負の値、および一般的なゼロ以外の値は、条件として使用される場合にtrueとして扱われます。

Cには、式が条件として扱われる多くのコンテキストがあります。条件は、必ずしもboolまたは__Bool_型ではありません。このタイプは、1999年の標準によって言語に追加されただけです。

これらのコンテキストの中で最も明白なのは、ifステートメントの式ですが、他の例もあります:while、_do-while_、forヘッダーの2番目の式、_?:_条件演算子の最初のオペランド、 _!_、_&&_、および_||_演算子のオペランド。 (私はと考えますこれは完全なリストですが、確かではありません。)

以下は、C標準がifステートメントの動作について述べていることです(「2つの形式」はif句の有無にかかわらずelseを指します)。

どちらの形式でも、式が0と等しくない場合、最初のサブステートメントが実行されます。

つまり、これは:

_if (foo) ...
_

これと同等です:

_if ((foo) != 0) ...
_

(演算子の優先順位の問題を回避するために、余分な括弧を追加します)。 fooint型の場合、意味は明確です。 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への変換として定義されていますが、結果は同じです。

これは質問のトピックから少し外れていますが、真の条件として扱われる値は必ずしもtrueequalとは限らないことに注意することが重要です。 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
_
5
Keith Thompson

0以外のものはすべてtrueに変換されます(Cの場合は1zero値は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に変換されます。[...]

これは、使用するコンパイラに関係なく保持されるはずです。

3
Shafik Yaghmour