如果你有一个类似NSString *someString的对象,那么它与下面哪个有什么不同(如果有):
if (!someString)
vs
的翻译是:vs。if (someString == nil)
谢谢!
如果你有一个类似NSString *someString的对象,那么它与下面哪个有什么不同(如果有):
if (!someString)
vs
的翻译是:vs。if (someString == nil)
谢谢!
你使用的第一个语法:
if (!someString)
利用 C 语言的一种“歧义”,因为最初的 C 标准缺乏适当的布尔类型。因此,任何等于 0 的整数值都被解释为“false”,而任何不为“0”的整数值则被视为“true”。因此,!
的含义基于这个约定进行定义,并且当前版本的 C 标准为了兼容性而保留了原始定义。
在您的特定情况下,someString
是一个指针,因此它首先被转换为整数,然后!someString
被解释为布尔值true
,当someString
指向位置0x000000
时,否则它将计算为“true”。
这在大多数情况下是可以的(我会说总是),但理论上,NULL/nil
在某些编译器下可能与0x000000
不同, 因此(在非常理论的情况下)最好使用第二种语法,这更加明确:
if (someString == nil)
无论如何,这种写法更易读,并且由于someString
不是整数(而是指针),在我看来,这通常是更好的实践。
编辑:关于NULL的定义...
C标准是否将NULL定义为0对我来说是一个有趣的话题...
根据C99标准,第7.17节,“公共定义”:
NULL [扩展为]实现定义的空指针常量;
因此,NULL在stddef.h中被定义为实现定义的空指针常量...同一文档在第47页声明:
值为0的整数常量表达式,或将这样的表达式强制转换为void*类型,称为空指针常量。55)如果将空指针常量转换为指针类型,则得到的指针称为空指针,保证与任何对象或函数的指针比较时都不相等。
因此,空指针常量(即(void*)0
)可以转换为空指针,这保证了与任何对象或函数的指针比较时都不相等。
因此,我认为这基本上取决于实现是否决定将将空指针常量转换为空指针的结果产生一个指针,将其转换回整数得到0。不清楚将空指针解释为整数是否等于0。
我认为标准确实试图强制将空指针设为0,但也为那些空指针不是0的系统留下了空间。对于大多数指针,它们是等效的,尽管我认识的大多数程序员更喜欢前者,因为它更加简洁。
对于弱链接符号,前者会解析该符号(如果缺失将导致崩溃),而显式与nil
或NULL
进行比较则不会。
C语言中的感叹号、惊叹号前缀操作符!
是一个逻辑非。至少它是逻辑非的一种版本。如果你看过典型的逻辑非真值表,你会看到类似这样的东西:
Input Result
1 0
0 1
然而在 C 语言中,逻辑非运算符的作用更像是这样:
Input Result
non-zero 0
0 1
if(5) printf("hello\n"); // prints hello
if(2029) printf("hello\n"); // also prints hello
在C语言中,任何非零的整数都会被认为是“真”。结合逻辑否定和等式的真值表,你很快就会意识到:
(! someString) and (someString == nil)
在所有意图上看,它们都是相同的!
那么,下一个合理的问题是,为什么更喜欢一种形式而不是另一种形式?从纯C的观点来看,这主要是风格问题,但大多数(好的)开发者会选择等式测试,原因如下:
在您的情况下,它意味着相同的事情。任何不指向 nil
的指针都将返回 YES
(true)。
通常感叹号运算符否定一个 BOOL
值。
foo == nil
。!foo
可以,但我个人认为有时候很容易忽略感叹号,所以我更喜欢写成foo == NO
。!
和==nil
具有相同的效果。!
是一个否定运算符。如果您的对象未被分配,那么您将从真值表中得到与 == nil
操作相同的结果。
但是,! 通常更多用于布尔运算。
if(!isFalse) {
//if isFalse == NO, then this operation evaluates to YES (true)
[self doStuff];
}
!
,例如!something
,它只是检查指针是否指向nil
,如果不是,则返回true,并且if语句将被执行。
0
或(void *)0
。即使用于空指针值的底层位模式不同,这也不会改变C中空指针常量表示为0
或(void *)0
的事实。 - dreamlax_Bool
。 - JAB