C/C++ でブール値として整数を評価するとき、負の数は真か偽か? コンパイラに関係なく、常に真/偽ですか?
5 に答える
ゼロ以外の値はすべて に変換されtrue
、ゼロの値は に変換されますfalse
。負の数がゼロ以外の場合、それらは に変換されtrue
ます。
C ++ 11標準からの引用(強調鉱山):
4.12 ブール変換 [conv.bool]
1 算術、スコープなし列挙、ポインター、またはメンバー型へのポインターの prvalue は、bool 型の prvalue に変換できます。ゼロ値、ヌル ポインター値、またはヌル メンバー ポインター値は に変換され
false
ます。その他の値は に変換されtrue
ます。std::nullptr_t 型の prvalue は 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
もちろん、「コンパイラに関係なく常に true/false ですか?」という質問の 2 番目の部分に答えるには、完全に確認する唯一の方法は仕様を確認することです。ただし、一般に、危険なことをするとコンパイラは警告します。上記の出力から、「ペダンティックな」警告があっても、gcc
このコードは完全に問題ないと見なされることがわかります。
簡単な回答: 負の値、および一般的にゼロ以外の値は、条件として使用されると true として扱われます。
C の場合、式が条件として扱われるコンテキストがいくつかあります。条件のタイプは、必ずしもbool
orではありません_Bool
。そのタイプは、1999 年の標準によってのみ言語に追加されました。
これらのコンテキストの中で最も明白なのはif
ステートメント内の式ですが、他にも例があります: while
, ,ヘッダーdo-while
の 2 番目の式,条件演算子の最初のオペランド, , , および演算子のオペランド。(これは網羅的なリストだと思いますが、確実ではありません。)for
?:
!
&&
||
ステートメントの動作について C 標準が述べていることは次のとおりです(「2 つの形式」とは、節がある場合とないif
場合を指します)。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++ の両方で、任意のスカラー (つまり、整数、浮動小数点、またはポインター) 値を条件として使用でき、スカラーがゼロに等しい場合は条件が false になり、ゼロに等しくない場合は true になります。 . C では、これを との不等比較として定義してい0
ます。C++ はこれをbool
-- への変換として定義しますが、結果は同じです。
これは質問のトピックから少し外れていますが、真の条件として扱われる値が必ずしもに等しいとは限らないことに注意することが重要であることを述べておきますtrue
。true
( がある1
場合は C#include <stdbool.h>
にあり、C++ の type の一意の値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 の場合は 0 ) に変換されます。Cに関して、 C99ドラフト標準セクションを見ると、6.3.1.2
ブール型の段落1は次のように述べています。
スカラー値が _Bool に変換されるとき、値が 0 と等しい場合、結果は 0 です。それ以外の場合、結果は 1 です。
完全を期すために、セクション7.16
ブール型と値の段落2を見ると、次のように述べています。
The macro
bool
expands to _Bool.
C++に関しては、セクションブール変換のパラグラフ1のドラフトC++標準は次のように述べています(私の強調):4.12
算術、スコープなし列挙、ポインター、またはメンバー型へのポインターの prvalue は、bool 型の prvalue に変換できます。ゼロ値、NULL ポインター値、または NULL メンバー ポインター値は false に変換されます。その他の値は true に変換されます。[...]
これは、使用するコンパイラに関係なく保持されます。
良い質問。答えは「依存」です。
if (-1) { // this is always true
}
一方、16 ビット マシンを使用しているとします。
if (-65536) { // this is always false
}
一方で、
int a = whatever doesn't matter;
if (a < 0) { // this might or might not be true
if (a) { // this will always be true if we get here
}
}
したがって、負の数は常に false とは限りませんが、常に false になる場合があります。