【问题标题】:! vs == nil in objective-c [duplicate]!在objective-c中vs == nil [重复]
【发布时间】:2011-10-10 13:32:57
【问题描述】:

如果你有一个像 NSString *someString 这样的对象,如果有的话,它们之间有什么区别

if (!someString)

if (someString == nil)

谢谢!

【问题讨论】:

    标签: iphone objective-c c


    【解决方案1】:

    在你的情况下,这意味着同样的事情。任何不指向nil 的指针都将返回YES (true)。

    通常感叹号运算符否定BOOL 值。

    【讨论】:

      【解决方案2】:

      对于大多数指针来说,它们是等价的,尽管我认识的大多数程序员更喜欢前者,因为它更简洁。

      对于弱链接符号,前者会解析符号(如果缺少它会导致崩溃),而与 nilNULL 的显式比较则不会。

      【讨论】:

        【解决方案3】:

        ! 是一个否定运算符。如果您的对象没有被分配,您将从真值表中得到与使用== nil 操作相同的结果。

        但是,!通常更多用于布尔运算。

        if(!isFalse) {
             //if isFalse == NO, then this operation evaluates to YES (true)
             [self doStuff];
        }
        

        当您在像!something 这样的对象上使用! 时,它只会检查指针是否指向nil,如果不是,则返回true,并触发if 语句。

        【讨论】:

          【解决方案4】:

          你使用的第一个语法:

           if (!someString)
          

          利用 C 的一种“歧义”,源于 C 的原始标准缺乏适当的布尔类型。因此,任何等于0的整数值都被解释为“假”,任何不等于“0”的整数值都被认为是“真”。因此,! 的含义是基于此约定定义的,并且当前版本的 C 标准保留了原始定义以实现兼容性。

          在您的具体情况下,someString 是一个指针,因此它首先被转换为整数,然后当someString 指向位置0x000000 时,! someString 被解释为true 的布尔值,否则它评估为“真”。

          这在大多数情况下都很好(我会说总是),但理论上,NULL/nil could be different from 0x000000 在某些编译器下,所以(在理论上)最好使用第二种语法,它更明确:

           if (someString == nil)
          

          无论如何它更具可读性,并且由于someString 不是整数(而是指针),IMO,一般来说是更好的做法。

          编辑:关于 NULL 的定义...

          C 标准是否将 NULL 定义为 0 对我来说是一个有趣的话题......

          根据C99 standard,第 7.17 节,“常用定义”:

          NULL [which] 扩展为实现定义的空指针常量;

          因此,在 stddef.h 中将 NULL 定义为 实现定义的空指针常量... 第 47 页的同一文件指出:

          值为 0 的整型常量表达式或转换为 void * 类型的表达式称为空指针常量。55) 如果将空指针常量转换为指针类型,则生成的指针称为空指针指针,保证不等于指向任何对象或函数的指针。

          因此,可以将空指针常量((void*)0转换为空指针,这样可以保证比较不等于指向任何对象或函数的指针。

          所以,我认为这基本上取决于实现是否决定将 null 指针常量 转换为 null 指针 的结果产生一个转换回整数给出 0。不清楚将 空指针解释为整数是否等于 0。

          我会说标准确实尝试强制空指针为 0,但对systems where the null pointer was not 0 敞开大门。

          【讨论】:

          • 我给了 +1,但 C 语言中关于布尔值的概念没有歧义——它根本不存在。
          • NULL 被 C 标准定义为 0(void *)0。即使用于空指针值的底层位模式不同,也不会改变 C 中空指针常量表示为 0(void *)0 的事实。
          • @Perception:在 C99 中可以。查看_Bool
          • @Perception:谢谢,我改进了措辞...
          • @dreamlax:也感谢您的评论,它促使我阅读了一些关于 NULL 主题的信息;这一切都归结为(void*)0 是否与 null 指针 相同,在我看来并非如此,因为标准将其称为 null 指针常量并谈到 转换为空指针...
          【解决方案5】:

          如果您要测试条件“foo is nil”,您应该说:foo == nil

          如果你的意思是测试一个布尔值是否为假,!foo 是可以的,但我个人认为一个瘦小的感叹号很容易错过,所以我更喜欢foo == NO

          编写好的代码不仅要向编译器清楚地传达你的意图,还要向出现的下一个程序员(可能是未来的你)传达你的意图。在这两种情况下,您对自己想要做的事情越明确越好。

          除此之外,!==nil 在我能想到的所有情况下都具有相同的效果。

          【讨论】:

            【解决方案6】:

            C 中的 bang、感叹号、! 前缀运算符是 逻辑非。至少,它是它的一个版本。如果您查看一个典型的逻辑非真值表,您会看到如下内容:

            Input       Result
              1            0
              0            1
            

            但是在 C 中,逻辑非运算符的作用更像这样:

            Input       Result
            non-zero      0
               0          1
            

            因此,当您考虑到 Objective-C 中的 NULL 和 nil 都计算为 0 时,您知道应用于它们的逻辑非运算符将导致 1。

            现在,考虑 平等 == 运算符。它比较两个项目的值,如果相等则返回 1,否则返回 0。如果您将其结果映射到真值表,那么它看起来与逻辑非的结果完全相同。

            在 C 和 Objective-C 程序中,条件实际上是由 int 决定的,而不是真正的布尔值。这是因为在 C 中没有布尔数据类型之类的东西。所以在 C 中编写这样的东西非常好:

            if(5) printf("hello\n"); // prints hello
            

            另外

            if(2029) printf("hello\n"); // also prints hello
            

            基本上,任何非零 int 在 C 中都将评估为“真”。您将其与逻辑否定和相等的真值表结合起来,您很快就会意识到:

            (! someString) and (someString == nil)
            

            所有意图都相同!

            所以下一个合乎逻辑的问题是,为什么更喜欢一种形式而不是另一种形式?从纯 C 的角度来看,这主要是一种风格,但大多数(优秀)开发人员会出于多种原因选择相等测试:

            1. 它更接近您试图在代码中表达的内容。你 尝试检查 someString 变量是否为零。
            2. 它更便携。像 Java 这样的语言有一个真正的布尔类型。 您不能对它们的变量或它们的 NULL 使用 bang 表示法 定义。在需要的地方使用相等可以更容易移植 稍后将 C 语言转换为此类语言。
            3. Apple 可能会更改 nil 的定义。好的,不,他们不会!但它 确保安全永远不会受到伤害!

            【讨论】:

            • "任何非零 int 在 C 中都将评估为 'true'" 您能否更具体地解释一下如何将逻辑表达式评估为 (int)0 或 (int)1?比如说,[if(pointer)...],指针首先转换为 int [(int)pointer],然后 [if((int)pointer != 0)] 它的计算结果为 (int)1。会不会是指针是 64 位,而 int 是 32 位,并且当它转换为 int 时,更高的字节会被截断(if(0xffffffff00000000) => if((int)0x00000000))?我很高兴知道我可能错在哪里。
            猜你喜欢
            • 1970-01-01
            • 2017-01-03
            • 1970-01-01
            • 2014-08-23
            • 1970-01-01
            • 1970-01-01
            • 2015-07-10
            • 2014-09-02
            • 2010-10-08
            相关资源
            最近更新 更多