【问题标题】:Is it safe to compare boolean variable with 1 and 0 in C, C++? [duplicate]在 C、C++ 中将布尔变量与 1 和 0 进行比较是否安全? [复制]
【发布时间】:2014-03-19 18:18:55
【问题描述】:

考虑代码

bool f() { return 42; }

if (f() == 1)
    printf("hello");

C(C99+ 和 stdbool.h)和 C++ 标准是否保证会打印“hello”?有没有

bool a = x;

总是等价于

bool a = x ? 1 : 0;

【问题讨论】:

  • 我确定这个问题是重复的,但是bool 类型的prvalue 可以转换为int 类型的prvalue,false 变为0,true 变为1
  • 为什么要这样比较?
  • 正是苏小歌所说的:你为什么还要在意?这样的代码永远不会像显式编写 falsetrue 那样富有表现力。
  • @XiaogeSu:我为 MCU 编码,我的布尔值通常是逻辑电平,例如if (gpio_read(jumper) == 1) gpio_write(led, 1);。它比简单的if (gpio_read(jumper))== true 更具可读性。
  • 我原以为你会打印“生命的意义”。而不是“你好”:)

标签: c++ c


【解决方案1】:

在 C++ 中,bool 是一个内置类型。从任何类型到bool 的转换总是产生false (0) 或true (1)。

在 1999 ISO C 标准之前,C 没有内置的布尔类型。程序员定义自己的布尔类型是(现在仍然是)很常见的,例如:

typedef int BOOL;
#define FALSE 0
#define TRUE 1

typedef enum { false, true } bool;

任何此类类型的大小至少为 1 个字节,并且可以存储 01 以外的值,因此与 01 的相等比较可能是不安全的。

C99 增加了一个内置类型_Bool,其转换语义类似于C++ 中bool 的转换语义;如果你有#include <stdbool.h>,它也可以称为bool

在 C 或 C++ 中,行为未定义的代码可能会在 bool 对象中存储 0 或 1 以外的值。例如,这个:

bool b;
*(char*)&b = 2;

将(可能)将值2 存储在b 中,但C++ 编译器可能假定它的值是01;像b == 0b == true 这样的比较可能成功也可能失败。

我的建议:

  • 不要编写在 bool 对象中存储奇怪值的代码。
  • 不要将 bool 的相等或不相等值与 01falsetrue 进行比较。

在你的例子中:

bool f() { return 42; }

假设这是 C++ 或带有 <stdbool.h> 的 C,此函数将返回 true 或等效的 1,因为将 42 转换为 bool 会产生 1

if (f() == 1)
    printf("hello");

由于您没有构造任何奇怪的bool 值,因此它的行为很好,将打印"hello"

但是明确地进行比较是没有意义的。 f() 已经是 bool 类型,所以它已经可以用作条件。您可以(并且可能应该)只写:

if (f())
    printf("hello");

f() == 1 并不比写(f() == 1) == 1) 更有帮助。

在一个真实的程序中,大概你会给你的函数一个有意义的名字,清楚地表明它的值代表一个条件:

if (greeting_required())
    printf("hello");

【讨论】:

  • @Corvus:我强烈反对 == 1 使条件更具可读性。我发现if (greeting_required())if (greeting_required() == 1) 更具可读性——即使函数返回int,前者也是正确的。不,该标准不能防止*(char*)b = 2
【解决方案2】:

是的。你错过了一步。 "0" 为假,其他所有 int 为真,但 f() 始终返回真 ("1")。它不返回 42,转换发生在“return 42;”中。

【讨论】:

  • 谢谢。我的疑虑来自于我在没有布尔类型的情况下用 C 语言编写,只使用 hack typedef unsigned char bool。在这种情况下,我的代码中的“hello”将不会打印出来。
【解决方案3】:

在 C 宏中 bool(我们说的是在 stdbool.h 中定义的宏)扩展为只有两个值 0 和 1 的 _Bool

在 C++ 中,表达式 f() == 1 中 f() 的值根据积分提升隐式转换为 int 1。

所以我认为这段代码

bool f() { return 42; }

if (f() == 1)
    printf("hello");

是安全的。

【讨论】:

  • C 有bool??从何时起?我猜想我落后了.. AFAIK,BOOL 是任何 > 0 并且 FALSE 是 0?类似于 WinAPI 的 BOOL,它被定义为 INT,可以是任何非 0 的东西。是吗?我不知道我猜.. 我通常看到typedef enum boolean{false, true};
  • @CantChooseUsernames 我们说的是在 stdbool.h 中定义的宏 bool
  • 哦.. 无论如何我要 +1。不知道它有那个。
  • @CantChooseUsernames:C 自 1999 年以来就内置了布尔类型。
  • @Corvus 实际上它不是布尔类型。它是一个具有两个值域的整数类型。:)
【解决方案4】:

我所知道的唯一对 C99 之前的环境有用的真正技巧是双重否定

int a = 42;
if ( (!!a) != 0 ) printf("Hello\n");

这将打印Hello,因为!! 操作的结果是一个布尔值,当值为非零时为true,否则为false。但这将花费你 2 次否定来获得你想要的布尔值,在现代标准中这是多余的,因为没有 !! 你会得到相同的结果,这是语言授予的结果。

【讨论】:

    猜你喜欢
    • 2022-06-10
    • 1970-01-01
    • 2019-08-05
    • 2012-04-24
    • 1970-01-01
    • 2017-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多