【问题标题】:Do Apple templates contain a bug since they cast to BOOL?Apple 模板是否包含错误,因为它们转换为 BOOL?
【发布时间】:2012-12-04 15:55:28
【问题描述】:

根据Mike Ash's blog post,转换为 BOOL 可能会失败 6%,因为指针大于 BOOL。因此,他建议如果您正在检查对象是否存在,则应检查 nil

if (self != nil) {

而不是 Apple 模板所做的是

if (self) {

Apple 的模板是否包含错误或是否有其他一些我不知道的语法糖?

【问题讨论】:

  • Daij-Djan:抱歉,我不是故意惹恼的,只是 1+ 部分让它有点晦涩。
  • Mike Ash 的帖子实际上并没有谈论if,而是一起投向BOOL。它们在不同的部分中,分别讨论不同的陷阱:关于if 的第一个是关于诸如0 <= i < count 之类的链式比较,而您正在谈论的部分是关于诸如return 之类的情况语句和赋值(实际上是转换为目标类型)。

标签: objective-c cocoa-touch cocoa boolean null


【解决方案1】:

因为他们转换为 BOOL

不,他们没有。根本没有演员表演。然而,有一个表达式的评估作为一个逻辑值。在指针的情况下(nilself 是),NULL 指针的计算结果为 false,否则为 true。这不是错误,只是一种简写方式,它是完全有效的 C。

关于为什么要与NULLnil 进行显式比较:在某些情况下,它可能更具可读性,尤其是在乍一看表达式的类型和范围并不明显的情况下。然而,在 Objective-C 和 Cocoa 中,在构造函数中执行此操作非常常见,任何有经验的程序员都会毫无问题地掌握它。

【讨论】:

  • @0x7fffffff 谢谢! :D 好吧,至少你可以在必要时修复我的英语(刚刚发生 :P)
  • 我不会太担心你的英语。我住在美国,显然我们这个年龄段的很多人都认为扼杀英语应该是一种趋势。我只是说你的英语比我认识的许多以英语为母语的人都好。
  • @0x7fffffff 真的很高兴听到这个消息 :) 鉴于法语拼写和拼写通常也是如此,我可能应该考虑获得语言硕士学位而不是 CS 硕士学位。 . ;-) 别担心,在我的国家匈牙利,同样的现象也存在,主要是在年轻人中——我一直在努力不落入这个“愚蠢的少年”类别。
  • @SteveMoser 为什么要不同?
  • 来自 Java 和类似背景的人的旁注。在像 Java 这样的语言中,没有办法评估不是布尔值的表达式。 Java 不接受 if (my_integer)if (this) 只有 if (0 != my_integer)if (null != this) 在那里有效。最好清楚地说明,在 C(和 Objective C)中,表达式是在严格的规则下评估的,但没有任何强制转换。
【解决方案2】:

Objective-C 基于 C,而在 C 中,if 语句确实(可能令人惊讶)不对布尔值进行操作。

C 具有类型层次结构:

  • char、整数和枚举 (enum) 类型是整数类型
  • floatdoublelong double真正的浮动类型
  • 有三种复数类型,它们与真正的浮点类型一起被简称为浮点类型
  • 整数类型和浮点类型组合形成算术类型
  • 算术类型和指针类型构成标量类型

呼!

现在到if 声明,它是以下形式之一:

if ( expression ) statement
if ( expression ) statement else statement

其中表达式必须是任何标量类型。如果表达式比较不等于 0,则执行第一个(或唯一)statement,如果表达式比较等于 0,则执行第二个(如果存在)statement

所以:

if (self) ...

if (self != nil) ...

结果中是相同的。

第一个表达式self 是一些指针类型,它是一个标量类型,并且被比较为不等于指针类型的零(在代码中由nil 表示)。第二个表达式self != nil 是一个相等表达式,产生int 类型的01,这也是一个标量类型...

所以从技术上讲,第二种形式涉及int 值的中间生成,但实际上没有编译器会生成一个(当然,除非您将表达式的结果分配给变量)。

注意事项:

  1. 有点奇怪if ( sin( angle ) ) ... 是有效的...
  2. switch 语句作用于 整数类型 而不是 标量类型

HTH

【讨论】:

  • 另外一点,除了if的定义之外,这个定义来自C。BOOL在C中是不存在的;它在一个 Objective-C 头文件中定义,并且是 Objective-C 的扩展。因此,它不能成为 C 定义的任何定义的一部分。(C99 中有一个本机布尔类型,但它与 BOOLif 的定义是分开的。)
  • @PeterHosey - 它可能是特殊的C,因为它只是一个typedef(对于signed char)不是一个新类型,所以它不太可能 而不是 cannot ;-)
【解决方案3】:

不,如果指针不为零,这不会失败,它是安全的,唯一的区别是语法,我不会推荐一种或另一种方式,因为它们是相同的。 您没有将 self 强制转换为 BOOL,您只是在检查 self 是否不为零。

【讨论】:

  • 这可能会失败,请参阅 Inder 的回答。
  • @H2CO3 和我的编辑一样。我正在记录错误的调试消息
  • Inders 的回答并不能证明if (self) 会失败,请参阅我对该回答的评论。
  • 我的答案是对的,可能你理解错了。所以我编辑了我的答案,进入了迂腐模式。
【解决方案4】:

已编辑
根据马丁的评论,我记录了错误的调试消息。 一样的

这是一个简单的测试

NSString *str = nil;
// suppose our string points to a string object whose starting address is 0x4500
//I'm assigning it manually so that I can test
str = 0x4500;
NSLog(@"%d",str);
if (str) {
    NSLog(@"It's non-nil");
}
else {
    NSLog(@"It's nil");
}

if (str == nil) {
    NSLog(@"It's nil");
}
else {
    NSLog(@"It's non-nil");
}

输出是:

It's non-nil
It's non-nil

【讨论】:

  • 你的第一个测试错了:if (str) { NSLog(@"It's nil"); } ...没有意义,应该是if (str) { NSLog(@"It's non-nil"); } ...!!然后你会看到if (str)if (str != nil) 总是有相同的结果。
  • @H2CO3 我记录了错误的输出。现在编辑了我的答案,正如您的分析器所期望的那样
  • @InderKumarRathore 我之前的评论没有讽刺意味。感谢您指出这究竟是如何被打破的。
  • @MartinR 感谢您的收获。从那时起,我一直在寻找这个问题。现在我松了一口气,苹果做对了:)。因此,上面的博客在这个例子中似乎是错误的
  • 博客仅声明您不应将指针转换为 BOOL。但正如 H2CO3 正确所说,if (self) 不会将self 转换为 BOOL。所以博客和苹果都是对的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-18
  • 1970-01-01
  • 1970-01-01
  • 2012-01-04
  • 2011-03-24
  • 1970-01-01
相关资源
最近更新 更多