在 C/C++ 中将整数评估为布尔值时,负数是真还是假?无论编译器如何,它们总是对/错吗?
5 回答
所有非零值都将转换为true
,零值将转换为false
。负数非零时,它们被转换为true
.
引用 C++11 标准(强调我的):
4.12 布尔转换 [conv.bool]
1 算术、无范围枚举、指针或指向成员类型的指针的纯右值可以转换为 bool 类型的纯右值。零值、空指针值或空成员指针值转换为
false
; 任何其他值都转换为true
. std::nullptr_t 类型的纯右值可以转换为 bool 类型的纯右值;结果值为假。
无论编译器如何,它们总是对/错吗?
只有当您的编译器符合标准或至少符合标准的这一特定部分时,您才会获得上述保证。实际上,所有编译器都具有这种标准行为,因此无需担心太多。
您可以通过编译它自己测试它:
#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 为真
$ ./test-cpp
-1 为真
当然,要回答您问题的第二部分,“无论编译器如何,它们总是对/错吗?”,唯一完全确定的方法是查看规范。不过,一般来说,如果你做了危险的事情,编译器会警告你,你可以从上面的输出中看到,即使有“pedantic”警告,也gcc
认为这段代码非常好。
简短回答:负值和一般的任何非零值在用作条件时都被视为真。
对于 C,有许多上下文将表达式视为条件。条件不一定是类型bool
或_Bool
;该类型仅由 1999 年标准添加到语言中。
这些上下文中最明显的是if
语句中的表达式,但还有其他示例:while
, ,标题do-while
中的第二个表达式,条件运算符的第一个操作数,以及, 和运算符的操作数。(我认为这是一个详尽的清单,但我不确定。)for
?:
!
&&
||
以下是 C 标准对语句行为的if
说明(“两种形式”指的是if
有子句和没有else
子句):
在这两种形式中,如果表达式比较不等于 0,则执行第一个子语句。
这意味着:
if (foo) ...
相当于:
if ((foo) != 0) ...
(添加额外的括号以避免任何运算符优先级问题)。foo
if是 type ,意思很清楚int
。如果foo
是某种浮点类型,0
则转换为相同的类型(如果值恰好是负零或 NaN,这可能会导致一些细微差别)。而如果foo
是指针,0
则被视为空指针常量;if (ptr)
等价于if (ptr != NULL)
(假设 的定义NULL
可见)。
对于 C++,规则的表述略有不同,但效果是一样的。C++if
语句中的条件被转换为类型bool
(与 C 不同,类型bool
自 C++ 的早期历史以来就已内置到 C++ 中)。bool
C++ 标准将任何标量类型的值转换为:
零值、空指针值或空成员指针值转换为false;任何其他值都将转换为 true。std::nullptr_t类型的纯右值可以转换为bool类型的纯右值;结果值为false。
因此在 C 和 C++ 中,任何标量(即整数、浮点或指针)值都可以用作条件,如果标量等于 0,则条件为假,如果不等于 0,则条件为真. C 将此定义为与 ; 的不等式比较0
。C++ 将其定义为对 -- 的转换,bool
但结果是一样的。
这有点偏离问题的主题,但我会提到重要的是要注意被视为真实条件的值不一定等于. (如果您有,则在 C 中,并且在 C++ 中具有唯一的 type 值)只是在条件中使用时具有“真实性”的众多值之一。这就是为什么你几乎不应该写:true
true
1
#include <stdbool.h>
bool
if (cond == true) ...
在 C 或 C++ 中(除非你真的需要将它与那个值进行比较);写吧:
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
Boolean type and values部分,第2段说:
The macro
bool
expands to _Bool.
关于C++,布尔转换第1段中的C++ 标准草案说(强调我的):4.12
算术、无范围枚举、指针或指向成员类型的指针的纯右值可以转换为 bool 类型的纯右值。将零值、空指针值或空成员指针值转换为 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
}
}
所以负数并不总是假的,除了有时它们总是假的。