63

在 C/C++ 中将整数评估为布尔值时,负数是真还是假?无论编译器如何,它们总是对/错吗?

4

5 回答 5

75

所有非零值都将转换为true,零值将转换为false。负数非零时,它们被转换为true.

引用 C++11 标准(强调我的):

4.12 布尔转换 [conv.bool]

1 算术、无范围枚举、指针或指向成员类型的指针的纯右值可以转换为 bool 类型的纯右值。零值、空指针值或空成员指针值转换为false; 任何其他值都转换为true. std::nullptr_t 类型的纯右值可以转换为 bool 类型的纯右值;结果值为假。


无论编译器如何,它们总是对/错吗?

只有当您的编译器符合标准或至少符合标准的这一特定部分时,您才会获得上述保证。实际上,所有编译器都具有这种标准行为,因此无需担心太多。

于 2013-09-17T02:39:43.430 回答
8

您可以通过编译它自己测试它:

#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认为这段代码非常好。

于 2013-09-17T02:46:45.880 回答
6

简短回答:负值和一般的任何非零值在用作条件时都被视为真。

对于 C,有许多上下文将表达式视为条件。条件不一定是类型bool_Bool;该类型仅由 1999 年标准添加到语言中。

这些上下文中最明显的是if语句中的表达式,但还有其他示例:while, ,标题do-while中的第二个表达式,条件运算符的第一个操作数,以及, 和运算符的操作数。(我认为这是一个详尽的清单,但我不确定。)for?:!&&||

以下是 C 标准对语句行为的if说明(“两种形式”指的是if有子句和没有else子句):

在这两种形式中,如果表达式比较不等于 0,则执行第一个子语句。

这意味着:

if (foo) ...

相当于:

if ((foo) != 0) ...

(添加额外的括号以避免任何运算符优先级问题)。fooif是 type ,意思很清楚int。如果foo是某种浮点类型,0则转换为相同的类型(如果值恰好是负零或 NaN,这可能会导致一些细微差别)。而如果foo是指针,0则被视为空指针常量;if (ptr)等价于if (ptr != NULL)(假设 的定义NULL可见)。

对于 C++,规则的表述略有不同,但效果是一样的。C++if语句中的条件被转换为类型bool(与 C 不同,类型bool自 C++ 的早期历史以来就已内置到 C++ 中)。boolC++ 标准将任何标量类型的值转换为:

零值、空指针值或空成员指针值转换为false;任何其他值都将转换为 true。std::nullptr_t类型的纯右值可以转换为bool类型的纯右值;结果值为false

因此在 C 和 C++ 中,任何标量(即整数、浮点或指针)值都可以用作条件,如果标量等于 0,则条件为假,如果不等于 0,则条件为真. C 将此定义为与 ; 的不等式比较0。C++ 将其定义为对 -- 的转换,bool但结果是一样的。

这有点偏离问题的主题,但我会提到重要的是要注意被视为真实条件的值不一定等于. (如果您有,则在 C 中,并且在 C++ 中具有唯一的 type 值)只是在条件中使用时具有“真实性”的众多值之一。这就是为什么你几乎不应该写:truetrue1#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
于 2013-09-18T03:13:44.087 回答
3

任何不是的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。[...]

无论您使用哪种编译器,这都应该成立。

于 2013-09-17T02:41:37.853 回答
-3

好问题。答案是“取决于”。

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
    }
}

所以负数并不总是假的,除了有时它们总是假的。

于 2013-09-17T03:03:05.720 回答