【问题标题】:Is there a difference between YES/NO,TRUE/FALSE and true/false in objective-c?在objective-c中YES/NO,TRUE/FALSE和true/false之间有区别吗?
【发布时间】:2010-10-11 13:41:28
【问题描述】:

真的很简单的问题;这些值之间是否存在差异(BOOL 和 bool 之间是否存在差异)?一位同事提到他们在 Objective-C 中评估不同的东西,但是当我查看他们各自 .h 文件中的 typedef 时,YES/TRUE/true 都被定义为 1 和 NO/FALSE/false 都是定义为0。真的有区别吗?

【问题讨论】:

  • 从实际的角度来看没有区别。您可能可以使用各种技巧来展示差异,但您通常会误入“未定义行为”领域。
  • 关于这个话题,我建议你看看我的有趣问题:stackoverflow.com/q/65517700/5492956 你可以看到YEStrue 的细微差别。

标签: objective-c boolean


【解决方案1】:

不,YES/NO 是指 TRUE/FALSE(1/0) 的不同方式

【讨论】:

    【解决方案2】:

    没有实际区别提供您使用BOOL 变量作为布尔值。 C 会根据布尔表达式的计算结果是否为 0 来处理布尔表达式。所以:

    if(someVar ) { ... }
    if(!someVar) { ... }
    

    意思相同

    if(someVar!=0) { ... }
    if(someVar==0) { ... }
    

    这就是为什么您可以将任何原始类型或表达式评估为布尔测试(包括,例如指针)。请注意,您应该做前者,而不是后者。

    请注意,如果将钝值分配给所谓的BOOL 变量并测试特定值,则存在差异,因此请始终将它们用作布尔值和仅从它们的 #define 值中分配它们。

    重要的是,永远不要使用字符比较来测试布尔值——这不仅是有风险的,因为someVar 可以被分配一个不是 YES 的非零值,而且在我看来更重要的是,它无法正确表达意图:

    if(someVar==YES) { ... } // don't do this!
    if(someVar==NO ) { ... } // don't do this either!
    

    换句话说,按照预期和记录使用的构造来使用,这样您就不会在 C 语言中受到伤害。

    【讨论】:

      【解决方案3】:

      我认为他们在许多情况下添加“是/否”以更加不言自明。例如:

      [button setHidden:YES];
      

      听起来比

      [button setHidden:TRUE];
      

      【讨论】:

      • 我不同意;对我来说,他们俩读的一样。但是,在外行人的 UI 中,我认为是/否看起来更好。
      • 我也不同意。如果有的话,它读起来很糟糕,因为它没有遵守多年来在其他语言中使用的不成文标准。 IE 是当您未能遵守大量标准时发生的情况的一个典型例子。
      • 对 2 个不精确的答案投一半反对票,对 signing your answers 投一半反对票
      【解决方案4】:

      您可能想阅读此question 的答案。总之,在 Objective-C 中(来自 objc.h 中的定义):

      typedef signed char        BOOL; 
      // BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
      // even if -funsigned-char is used.
      #define OBJC_BOOL_DEFINED
      
      
      #define YES             (BOOL)1
      #define NO              (BOOL)0
      

      【讨论】:

        【解决方案5】:

        我相信boolBOOL 之间存在区别,请查看此网页了解原因:
        http://iosdevelopertips.com/objective-c/of-bool-and-yes.html

        因为BOOLunsigned char 而不是原始类型,所以BOOL 类型的变量可以包含YESNO 以外的值。

        考虑这段代码:

        BOOL b = 42;
        
        if (b) {
            printf("b is not NO!\n");
        }
        
        if (b != YES) {
            printf("b is not YES!\n");
        }
        

        输出是:

        b 不是 NO!
        b 不是 YES!

        对于大多数人来说,这是一个不必要的问题,但如果你真的想要一个布尔值,最好使用bool。我应该补充一点:iOS SDK 通常在其接口定义上使用BOOL,所以这是坚持使用BOOL 的一个论据。

        【讨论】:

        • 但请注意,最初的 C 实现没有 bool,因此传统上使用 intchar 作为布尔值,有时使用 #define 来隐藏差异有时不是。事实上,我不确定即使是当前的标准是否要求 bool 以一种阻止检查其内部结构的方式实施。
        • 虽然,第一个printf 会说谎。 b 的值不是YES,它是“非零”,这是条件测试的内容。所以你应该有printf("b is not zero"),它不一定和YES一样。在这种情况下,b 既是“非零”又是“非 YES”。
        • 谢谢劳伦斯,我已经按照这些思路进行了更新。
        • 确实,我在 Xcode 8.2 中没有得到第二个输出。我哪里失败了?
        • @HotLicks 0,不是零,假和真之间没有内在的区别。只要该值是逻辑布尔值,它将始终具有此接口以保持二进制兼容性。当您使用看起来像布尔值的非布尔值时,问题就开始了,例如 c 标准库应用程序入口函数,main 在成功时返回 0,许多人最终将此 0 视为布尔值,而实际上它是应用程序定义的枚举或用户定义的值,被调用者通常期望在异常终止时不为零。
        【解决方案6】:

        我对此进行了详尽的测试。我的结果应该说明一切:

        //These will all print "1"
        NSLog(@"%d", true == true);
        NSLog(@"%d", TRUE == true);
        NSLog(@"%d", YES  == true);
        NSLog(@"%d", true == TRUE);
        NSLog(@"%d", TRUE == TRUE);
        NSLog(@"%d", YES  == TRUE);
        NSLog(@"%d", true == YES);
        NSLog(@"%d", TRUE == YES);
        NSLog(@"%d", YES  == YES);
        
        NSLog(@"%d", false == false);
        NSLog(@"%d", FALSE == false);
        NSLog(@"%d", NO    == false);
        NSLog(@"%d", false == FALSE);
        NSLog(@"%d", FALSE == FALSE);
        NSLog(@"%d", NO    == FALSE);
        NSLog(@"%d", false == NO);
        NSLog(@"%d", FALSE == NO);
        NSLog(@"%d", NO    == NO);
        
        
        //These will all print "0"
        NSLog(@"%d", false == true);
        NSLog(@"%d", FALSE == true);
        NSLog(@"%d", NO    == true);
        NSLog(@"%d", false == TRUE);
        NSLog(@"%d", FALSE == TRUE);
        NSLog(@"%d", NO    == TRUE);
        NSLog(@"%d", false == YES);
        NSLog(@"%d", FALSE == YES);
        NSLog(@"%d", NO    == YES);
        
        NSLog(@"%d", true == false);
        NSLog(@"%d", TRUE == false);
        NSLog(@"%d", YES  == false);
        NSLog(@"%d", true == FALSE);
        NSLog(@"%d", TRUE == FALSE);
        NSLog(@"%d", YES  == FALSE);
        NSLog(@"%d", true == NO);
        NSLog(@"%d", TRUE == NO);
        NSLog(@"%d", YES  == NO);
        

        输出是:

        2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.072 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.076 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
        2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.082 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.091 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.092 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.097 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.098 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.101 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0
        2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0
        

        【讨论】:

        • [[NSObject]alloc]init] 不等于 TRUE 或 YES。因此使用 if ([[NSObject]alloc]init]==TRUE) 测试对象初始化将失败。我从来没有对定义单一“真”值的语言感到满意,而实际上任何非零值都可以。
        • @SamuelRenkert 我对在ifwhile 中采用非布尔值的语言感到不舒服。就像... while("guitar gently weeps") 不应该工作...
        • @SamuelRenkert 也是 2003 年发现的 Linux 后门:if (user_id = ROOT_UID)
        【解决方案7】:

        这里没有人提到一个微妙的错误,我想我应该包括......更多的是一个逻辑错误:

        int i = 2;
        if(i);        //true
        if(i==YES);   // false
        if((!!i)==YES); //true
        

        所以这里的问题只是 (YES==1) 和 C 中的比较不是布尔值,而是基于值的比较。

        因为YES 只是一个#define(而不是语言固有的东西),所以它必须具有某种价值,而1 最有意义。

        【讨论】:

        • 这与 DanJ 的答案基本相同,从 2 年前开始,但细节较少。
        • @LawrenceDol 我不知道,它提到 YES 只是 #defined 为 1,而不是语言固有的,就像它可能是更高级别的语言一样......有人可能会得到从中的价值......但是很好的拖钓,和你一起。
        【解决方案8】:

        trueYES 之间的主要(危险!)区别在于 JSON 序列化。

        例如,我们有JSON类型的服务器请求,需要在json sence中发送true/false:

        NSDictionary *r1 = @{@"bool" : @(true)};
        NSDictionary *r2 = @{@"bool" : @(YES)};
        NSDictionary *r3 = @{@"bool" : @((BOOL)true)};
        

        然后我们将其转换为 JSON 字符串,然后发送为

        NSData *data = [NSJSONSerialization  dataWithJSONObject:requestParams options:0 error:nil];
        NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        

        结果是

        jsonString1 // {"bool":1}
        jsonString2 // {"bool":true}
        jsonString3 // {"bool":true}
        

        由于 API 逻辑jsonString1 可能会导致错误。

        所以要小心 Objective-C 中的布尔值。

        总而言之,只有精确的@YES 和转换为@((BOOL)expression) 的值是__NSCFBoolean 类型,并通过JSON 序列化转换为true。 任何其他表达式,如 @(expression1 && expression2)(甚至是 @(YES && YES))都是 __NSCFNumber (int) 类型,并在 JSON 中转换为 1

        附:您可以简单地使用字符串值的布尔值

        @{@"bool" : @"true"}; // in JSON {"bool":true}
        

        【讨论】:

          【解决方案9】:

          首先让我们来看看什么是真假,以及是什么赋予了它们意义。

          我们可以在 lambda 演算中构造一个名为 if a then b else c 的结构,如下所示:

          (\ifThenElse. <use if then else>)(\a. \b. \c. a b c)
          

          在 JavaScript 中,这看起来像这样:

          (function(ifThenElse) {
              // use ifThenElse
          })(function(a) {
              return function(b) {
                  return function(c) {
                      return a(b)(c);
                  };
              };
          });
          

          为了使 ifThenElse 有用,我们需要一个函数“true”来选择右或左,并在忽略另一个选项的情况下这样做,或者选择选项“true”的函数“false”不拿走。

          我们可以这样定义这些函数:

          (\true. <use true>)(\a. \b. a) and (\false. <use false>)(\a. \b. b)
          

          在 JavaScript 中是这样的:

          (function(True) {
              // use True
          })(function(a) {
               return function(b) {
                   return a;
               }
          });
          
          (function(False) {
              // use True
          })(function(a) {
               return function(b) {
                   return b;
               }
          });
          

          现在我们可以做以下事情了

          (\true. \false. \ifThenElse. \doThis. \doThat. ifThenElse true doThis doThat)
          (\a. \b. a)(\a. \b. b)(\a. \b. \c. a b c)(\a. ())(\a. ())
          

          doThis 和 doThat 是 (\a. ()) 因为 lambda 演算不提供任何服务,例如打印/数学/字符串,我们所能做的就是什么都不做,说我们做了(然后通过替换它来作弊)在我们的系统中提供我们想要的副作用的服务)

          让我们来看看它的实际效果。

          (function(True) {
              return (function(False) {
                  return (function(ifThenElse) {
                      return (function(doThis) {
                          return (function(doThat) {
                              return ifThenElse(True)(doThis)(doThat);
                          });
                      });
                  });
              })
          })(function(a) {
               return function(b) {
                   return a;
               }
          })(function(a) {
               return function(b) {
                   return b;
               }
          })(function(a) {
              return function(b) {
                  return function(c) {
                      return a(b)(c);
                  };
              };
          })(function(a) { console.log("you chose LEFT!"); })
          (function(a) {console.log("you chose RIGHT");})();
          

          如果我们被允许使用数组/映射/参数/或多个语句来拆分为多个函数,这是一个可以简化的深层环境,但我想保持尽可能纯洁,我可以将自己限制在以下函数中只有一个参数。

          请注意名称 True/False 没有内在意义,我们可以轻松地将它们重命名为 yes/no、left/right、right/left、0/one、apple/orange。它的意义在于,无论做出什么选择,都只是由做出它的选择者的种类造成的。因此,如果打印“LEFT”,我们知道选择器只能是真的,并且基于这些知识我们可以指导我们进一步的决策。

          总结一下

          function ChooseRight(left) {
              return function _ChooseRight_inner(right) {
                  return right;
              }
          }
          function ChooseLeft(left) {
              return function _ChooseLeft_inner(right) {
                  return left;
              }
          }
          
          var env = {
              '0': ChooseLeft,
              '1': ChooseRight,
              'false': ChooseRight,
              'true': ChooseLeft,
              'no': ChooseRight
              'yes': ChooseLeft,
              'snd': ChooseRight,
              'fst': ChooseLeft
          };
          var _0 = env['0'];
          var _1 = env['1'];
          var _true = env['true'];
          var _false = env['false'];
          var yes = env['yes'];
          var no = env['no'];
          
          // encodes church zero or one to boolean
          function lambda_encodeBoolean(self) {
              return self(false)(true);
          }
          // decodes a Boolean to church zero or one
          function lambda_decodeBoolean(self) {
              console.log(self, self ? env['true'] : env['false']);
              return self ? env['true'] : env['false'];
          }
          
          lambda_decodeBoolean('one' === 'two')(function() {
              console.log('one is two');
          })(function() {
              console.log('one is not two');
          })();
          
          lambda_decodeBoolean('one' === 'one')(function() {
              console.log('one is one');
          })(function() {
              console.log('one is not one');
          })();
          

          【讨论】:

            猜你喜欢
            • 2016-12-02
            • 1970-01-01
            • 2019-12-12
            • 2013-09-09
            • 2012-08-23
            • 2011-04-09
            • 2018-12-20
            • 1970-01-01
            相关资源
            最近更新 更多