【问题标题】:Evaluation (NSIntegers) inside if-statement Objective-Cif语句Objective-C中的评估(NSIntegers)
【发布时间】:2016-05-17 20:35:31
【问题描述】:

我很怀疑,为什么它可以正常工作:

NSInteger row = indexPath.row;
NSInteger preloadTrigger = self.nodes.count - 20;
if (row >= preloadTrigger) {
    [self.loader loadNextposts];
}

这不会(只是跳过 if 语句):

if (indexPath.row >= self.nodes.count - 20) {
    [self.loader loadNextposts];
}

self.nodes.count - 20 的值为负时。

但是,当表达式的值为正时,它总是可以正常工作。

一个非常奇怪的行为,因为我看不到两个表达式的语义差异。

更新: 所以,我决定测试一下:

(lldb) po self.nodes.count - 20
18446744073709551601

(lldb) po preloadTrigger
-15

【问题讨论】:

  • 试试 if (indexPath.row >= (self.nodes.count - 20)) {
  • 我确定-[NSArray count] 返回一个NSUIntegerun已签名)。不确定减去20not 20u)是否应该将其提升为已签名(不是 C 律师...),但它闻起来像那个方向的东西...跨度>
  • Avijit,不行,我一开始试过这个。
  • 如果把第二行的NSInteger改成NSUInteger,还能用吗?
  • @tapani 你能解释一下,具体在哪一行?

标签: ios objective-c if-statement conditional nsinteger


【解决方案1】:

我将对其他正确答案添加一些解释。

所以,事情是这样的:

self.nodes.count 是 NSUInteger 类型,在 64 位系统中与 unsigned long int 相同,或者在 32 位系统中与 unsigned int 相同。

文字20 的类型是int

当您形成表达式 self.nodes.count - 20 时,20 被“提升”为另一个操作数 (self.nodes.count) 的无符号整数类型,因为它具有两者中更大的范围。

这是因为,当两个操作数具有不同大小的类型时,较小的被提升为较大的,以使它们相等并以这些术语计算结果(在硬件中,不同类型的值之间的算术运算不是真正定义 - 位表示不同)。

问题在于,为了换取能够用相同的位长表示更广泛的正值,无符号整数不能表示负值。因此,当20 大于self.nodes.count 时,结果“环绕”为一个大的无符号整数。

另一方面,indexPath.row 也是一个无符号整数 (NSUInteger),因此您最终会将相对较小的行值与减法运算的巨大结果进行比较;测试:

if (indexPath.row >= self.nodes.count - 20)

...总是失败(左边更小)。

如果您首先将两个结果都转换为有符号整数,然后比较这些有符号整数:

NSInteger row = indexPath.row;
NSInteger preloadTrigger = self.nodes.count - 20;
if (row >= preloadTrigger) {

...然后不会发生包装/下溢,您会得到预期的结果。

【讨论】:

    【解决方案2】:

    根据Apple Docs,count 属性是objective-C 中的NSUInteger

    当你写的时候:

     NSInteger preloadTrigger = self.nodes.count - 20;
    

    实际上,您将count 转换为NSInteger 对象,如果count 不大于20,则可以有一个负值。

    但是当你写的时候:

    (indexPath.row >= self.nodes.count - 20)
    

    count 是一个NSUInteger 对象,从它减去 20 总是会得到一个正数(顺便说一下很大)。

    【讨论】:

      【解决方案3】:

      因为 nodes.count 是 NSUInteger 而 row 是 NSInteger。无符号整数 - 20 绝不是负值,但会产生一个巨大的正值,而您期望它是负值。

      【讨论】:

      • 我虽然也许编译器可能会将它提升为已签名,因为他正在减去(看似已签名的)文字 20...
      • 为什么编译器会假设 20 与无符号属性一起使用时是有符号的?
      • 这当然是问题所在,但仍然不清楚为什么这两个代码片段不同。请详细说明。
      • @Tapani 我不知道。但我知道你可以用20u 指定一个无符号文字,所以我假设20 默认为signed。然后,涉及(unsigned) - (signed) 的操作应该提升第一个操作数,以确保安全(再次,不确定整数是否是这样工作的)
      • 现在我看到了 what 正在发生的事情:促销朝另一个方向发展(已签名的 int 被“提升”为 uint),所以 count - 20 是未签名的(并且如果count 小于 20,则包装!)。这是有道理的: uint 的范围更广(如果只是在积极方面)。来源:stackoverflow.com/a/28133443/433373
      猜你喜欢
      • 1970-01-01
      • 2010-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-22
      • 1970-01-01
      相关资源
      最近更新 更多