【发布时间】:2011-10-10 13:32:57
【问题描述】:
如果你有一个像 NSString *someString 这样的对象,如果有的话,它们之间有什么区别
if (!someString)
对
if (someString == nil)
谢谢!
【问题讨论】:
标签: iphone objective-c c
如果你有一个像 NSString *someString 这样的对象,如果有的话,它们之间有什么区别
if (!someString)
对
if (someString == nil)
谢谢!
【问题讨论】:
标签: iphone objective-c c
在你的情况下,这意味着同样的事情。任何不指向nil 的指针都将返回YES (true)。
通常感叹号运算符否定BOOL 值。
【讨论】:
对于大多数指针来说,它们是等价的,尽管我认识的大多数程序员更喜欢前者,因为它更简洁。
对于弱链接符号,前者会解析符号(如果缺少它会导致崩溃),而与 nil 或 NULL 的显式比较则不会。
【讨论】:
! 是一个否定运算符。如果您的对象没有被分配,您将从真值表中得到与使用== nil 操作相同的结果。
但是,!通常更多用于布尔运算。
if(!isFalse) {
//if isFalse == NO, then this operation evaluates to YES (true)
[self doStuff];
}
当您在像!something 这样的对象上使用! 时,它只会检查指针是否指向nil,如果不是,则返回true,并触发if 语句。
【讨论】:
你使用的第一个语法:
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 敞开大门。
【讨论】:
0 或 (void *)0。即使用于空指针值的底层位模式不同,也不会改变 C 中空指针常量表示为 0 或 (void *)0 的事实。
_Bool。
(void*)0 是否与 null 指针 相同,在我看来并非如此,因为标准将其称为 null 指针常量并谈到 转换为空指针...
如果您要测试条件“foo is nil”,您应该说:foo == nil。
如果你的意思是测试一个布尔值是否为假,!foo 是可以的,但我个人认为一个瘦小的感叹号很容易错过,所以我更喜欢foo == NO。
编写好的代码不仅要向编译器清楚地传达你的意图,还要向出现的下一个程序员(可能是未来的你)传达你的意图。在这两种情况下,您对自己想要做的事情越明确越好。
除此之外,! 和 ==nil 在我能想到的所有情况下都具有相同的效果。
【讨论】:
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 的角度来看,这主要是一种风格,但大多数(优秀)开发人员会出于多种原因选择相等测试:
【讨论】: