! vs == nil in objective-c

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

if (!someString) 

VS

 if (someString == nil) 

谢谢!

您使用的第一个语法:

  if (!someString) 

利用C的一种“模糊性”,这是因为C的原始标准缺乏适当的布尔类型。 因此,任何等于0的整数值被解释为“假”,并且任何不同于“0”的整数值被视为“真”。 的意思! 因此,基于此约定定义了C标准的当前版本,保留了原始的兼容性定义。

在您的特定情况下, someString是一个指针,因此它首先转换为整数,然后! someStringsomeString指向0x000000位置时, ! someString被解释为bool值为true ,否则它将变为“true”。

这在大多数情况下都很好(我会说总是如此),但理论上,在某些编译器下, NULL/nil 可能与0x000000不同 ,因此(在非常理论上)最好使用第二种语法,它更明确:

  if (someString == nil) 

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

编辑:关于NULL的定义…

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

根据C99标准 ,第7.17节“通用定义”:

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

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

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

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

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

我会说标准真的尝试并强制将空指针设为0,但是对空指针不为0的系统保持开放。

对于大多数指针来说,它们是等价的,尽管我知道的大多数编码器都更喜欢前者,因为它更简洁。

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

砰的一声,感叹! C中的前缀运算符是逻辑不 。 至少,它是它的一个版本。 如果你看一个典型的逻辑非真值表,你会看到这样的东西:

 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中评估为“true”。您将它与逻辑否定和相等的真值表结合起来,您很快意识到:

 (! someString) and (someString == nil) 

对于所有意图相同!

所以下一个合乎逻辑的问题是,为什么更喜欢一种forms呢? 从纯粹的C观点来看,它主要是风格点,但大多数(好的)开发人员会选择相等测试,原因如下:

  1. 它更接近于您尝试在代码中表达的内容。 您正在尝试检查someString变量是否为nil。
  2. 它更便携。 像Java这样的语言有一个真正的布尔类型。 您不能对其变量或其NULL定义使用爆炸记号。 在需要时使用相等性可以使以后更容易将C语言移植到这些语言中。
  3. Apple可能会改变nil的定义。 好吧,不,他们不会! 但是安全永远不会伤害!

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

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

如果你的意思是测试条件“foo是零”你应该说: foo == nil

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

编写好的代码不仅可以清楚地向编译器传达您的意图,还可以传达给下一个程序员(可能是您的未来)。 在这两种情况下,你可以更明确地了解你正在尝试做什么,越好。

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

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

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

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

当你使用! 在一个像这样的对象上它只是检查指针是否指向nil ,如果没有,则返回true,if语句触发。