【问题标题】:In Objective-c, safe and good way to compare 2 BOOL values?在 Objective-c 中,比较 2 个 BOOL 值的安全和好方法?
【发布时间】:2012-06-21 08:31:43
【问题描述】:

我想比较 Objective-c 中的 2 个 BOOL 值。

我发现以下代码中的 (3)-(6) 有效。
(1)-(2) 不起作用,因为 BOOL 只是 signed char

(3) 有效且可读性强,但我认为 bool 不是客观 c。
在objective-c代码中使用bool好不好?

在 Objective-c 中比较 2 个 BOOL 值的安全和好方法是什么?
还有其他更好的比较方法吗?

BOOL b = YES;
BOOL c = 2;

NSLog(@"(1) %d", b == c); // not work
NSLog(@"(2) %d", (BOOL)b == (BOOL)c); // not work
NSLog(@"(3) %d", (bool)b == (bool)c);
NSLog(@"(4) %d", !b == !c);
NSLog(@"(5) %d", !!b == !!c);
NSLog(@"(6) %d", (b != 0) == (c != 0));

结果:

(1) 0
(2) 0
(3) 1
(4) 1
(5) 1
(6) 1

【问题讨论】:

  • 2 不是有效的BOOL 值;只有YESNO 是。你的做法是无效的。
  • 第四种方法我觉得不错。它很短,可以安全地将值转换为 0 或 1。
  • @trojanfoe:问题是,Obj-C 很乐意接受将数字分配给 BOOL,你甚至可以对它进行按位运算。
  • 我同意 trojanfoe,而且我认为 XCode 应该在此类分配的情况下生成警告。错误的 BOOL 分配是可怕错误的根源。
  • @NikolaiRuhe 当然,但是询问有关安全使用BOOL 的问题然后分配2 是无效的。

标签: iphone objective-c boolean compare


【解决方案1】:

比较两个布尔值应该使用 XOR 操作来处理。

试图直接比较两个布尔值是对布尔代数基础的误用: http://en.wikipedia.org/wiki/Boolean_algebra_(logic)

当你在做的时候

BOOL a = (b == c);

那么即使 b 和 c 都为真,这个值也可能返回假。但是,如果 b 和 c 都为真,即大于 0,则表达式 b && c 将始终返回 YES,否则返回 NO。

这才是你真正想要做的:

BOOL xor = b && !c || !b && c;
BOOL equal = !xor;

相当于

BOOL equal = !(b && !c || !b && c);

BOOL equal = (b && c) || (!b && !c)

如果您必须花时间确保您的 BOOL 值已标准化(即设置为 1 或 0),那么您做错了什么。

【讨论】:

  • 谢谢杰克!我认为你和@Sulthan 是对的。它很漂亮,但它比我更长,更不可读/可写!!或(布尔)。为什么 c 没有逻辑异或运算符?
  • 可读性可以通过变量名来提高。例如,如果您想检查一个人是饿了但不累还是累了但不饿,并且您有两个名称相同的布尔值,则表达式 (hungry && !tired) || (!hungry &&tire) 比表达 (hungry !=tire) 更有意义。 (怎么可能饿等于累,这意味着什么?)
  • OP的问题中的第4个表达式实际上快速而干净地解决了问题。它只会将数字标准化为 0 或 1,然后 == 的行为就像 XNOR(NOT XOR)。其他表达式(3和5、6)也是正确的。
  • 在编程上它是安全的,并且可能被某些人认为是“干净的”,但我认为布尔表达式应该是一个独立的表达式,它分解为仅使用 && 和有返回值真或假。将两个布尔表达式相互比较,无论是否标准化,都不是正则布尔代数。是:if(true) if(false) if(bool1&&bool2) if(bool1 && !bool2 || int1==int2) if(int1==int2) 等等。否: if(bool1==bool2) if(bool1==true) if(!bool1==bool2) 等等。它们在编程上都是正确的,但后者对我来说并不好看。
【解决方案2】:

在 Objective-C 中使用 bool 是完全有效的,因为它是 C99 标准的一部分(第 7.16 节)。在我看来,这也是处理布尔类型安全比较的最佳方式。

不到处使用bool 的唯一原因是BOOL 在Objective-C 和框架中无处不在。

【讨论】:

  • 我在任何地方都使用bool,除了Cocoa API 调用BOOL 的地方。从一个到另一个的安全转换是(foo 是 bool,bar 是 BOOL):foo = bar ? true : false;bar = foo ? YES : NO;
  • 谢谢。我认为 bool 是 C++。 @JeremyP,为什么 foo = bar; bar = foo; 不安全?
  • truefalse 分配给BOOL 既有效又安全。标准规定它们扩展为整数常量 01(也在 §7.16 中)。
  • @js_ 它总是有效的。使用现代非错误编译器,直接赋值也应该是安全的。
  • @JeremyP 那么你为什么要做foo = bar ? true : false;bar = foo ? YES : NO;? XCode 的编译器有问题?
【解决方案3】:

除了其他答案,我想指出比较布尔值是否相等不是一个非常常见的操作。 BOOL 不是一种类型,它只是一个宏,它隐藏了布尔值只是整数的事实。对于每个布尔运算,您应该使用可以将整数正确处理为布尔值的编程结构和运算符:

例如: if (condition1 == NO) {} 应该是 if (!condition1) {}

if (condition1 == condition2) {}
可以是
if ((condition1 && condition2) || (!condition1 && !condition2)) {}
或更好
BOOL newCondition = (condition1 && condition2) || (!condition1 && !condition2); if (newCondition) {}

编写条件的最短方式不一定是最好的方式。

【讨论】:

  • 我认为比较布尔值很少见。一种常见的情况是 BOOL 属性的设置器,具有快捷提前返回: - (void)setAnimate:(BOOL)animate { if (_animate == animate) return; // 否则做任何设置或拆除动画 }
  • 另外,为了正确起见:BOOL 不是宏,而是 typedef。
  • 感谢typedef 的注意。 旧值检查 非常特别。通常,您根本不关心属性类型,甚至不需要知道它是 BOOL。
【解决方案4】:

通过回答“2”是什么意思,将您的号码转换为有效的BOOL

在您的上下文中,是 2 = YES

Int number = 2;
BOOL c = (number == 2); //2 is YES

是 > 0 = 是

Int number = 2;
BOOL c = (number > 0); //2 is YES

这在很大程度上取决于您的应用程序中什么是真什么是假

【讨论】:

  • 谢谢。在得知 256 的倍数被隐式转换为 0(否)后,我总是在分配时尝试转换为有效的 BOOL。但是其他人创建的方法可能返回 0/1 以外的 BOOL 值。而且我不会将返回的 BOOL 值转换为像 b = !![obj methodWhchReturnsBOOL]; 这样的有效 BOOL 所以,c = 2 可能会发生。
  • 如果您正确使用 BOOL,则不需要这种转换。如果你需要考虑这一点,那么你做的事情根本上是错误的。即使 c 为 2 且 b 为 1,表达式 (B && C) 也将返回 YES。可以将所有代码都基于这些类型的表达式,这是布尔代数中的正确方法。 (这就是为什么它被称为 BOOL/bool/Boolean)请参阅我的答案以获取参考。
【解决方案5】:

来自objc.h

typedef signed char     BOOL; 
....

#define YES             (BOOL)1
#define NO              (BOOL)0

显然BOOL是signed char,所以你可以给BOOL类型的变量赋值是真的,这会弄乱比较(因为比较是整数比较)。

我认为您的 (4) 使用否定将任意整数值转换为 0 或 1 的方法是安全比较 2 BOOL 的逻辑值的好方法。

【讨论】:

    【解决方案6】:

    如果您将整数 2 分配给 BOOL 类型的变量,您的代码将被破坏。在那之后,无论你得到什么,这都是你应得的。

    因此,比较两个 BOOL a 和 b 的唯一合理方法是

    if (a == b) ...
    if (a != b) ...
    

    【讨论】:

    • 我想说,唯一明智的方法是 if(a && b)if (!a && b),因为这些运算符将不再是真正的布尔运算,而 ==!= 是数字运算符。
    猜你喜欢
    • 2011-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 2010-09-17
    相关资源
    最近更新 更多