1 & lt;-1的计算结果为TRUE



在我的部分代码中,我正在编写一个简单的for循环来迭代数组中的元素(所有NSMutableDictionary),我发现即使条件基本为1,循环也会执行<1 .

所以我写了下面的代码来测试这个问题的有效性:
NSMutableArray* arr = [[NSMutableArray alloc] init];
NSLog(@"COUNT: %d | %i", arr.count, 1 < (arr.count - 1));

输出为:

COUNT: 0 | 1

这实际上意味着计数为0,并且1小于-1。

我想这可能是因为数组刚刚初始化,也许添加和删除对象可能会改变一点所以我继续这样做:

NSMutableArray* arr = [[NSMutableArray alloc] init];
[arr addObject:@1];
[arr removeObject:@1];
NSLog(@"COUNT: %d | %i", arr.count, 1 < (arr.count - 1));

仍然是相同的结果:

COUNT: 0 | 1

我想到的可能的原因:

  • 有一些关于编译器/objective-C的东西,我还不明白
  • 在我的Mac寄存器闹鬼
  • 我快要疯了

我非常怀疑这是最后两种情况中的任何一种,但我还是想知道为什么会发生这种情况

arr.count为无符号整数值(类型为NSUInteger)。在无符号算术中,(0 - 1)会绕到一个非常大的正数,而-1不会。

如果将值强制转换为有符号整数,可能会看到预期的结果:

NSLog(@"COUNT: %d | %i", (int)arr.count, 1 < ((int)arr.count - 1));

查看这个主题的一些方法来处理这个常见的bug来源:常量bug从[NSArray count]是unsigned

发生这种情况的原因是左边的1被视为无符号。反过来,这是因为arr.count是无符号类型,使得表达式arr.count-1也是无符号的。当你从一个无符号零中减去1时,你会得到一个下溢,结果是一个非常大的数。

为了避免这样的问题,在处理unsigned类型的值时,要非常小心减法。更喜欢添加到另一边——特别是,而不是写

if (a < unsignedB - c)

if (a+c < unsignedB)

数组的count属性为NSUInteger类型,即unsigned long。表达式arr.count - 1从无符号整数中减去1,因此结果也是无符号的。因为溢出,你得到的不是-1而是一个非常大的正数,这个数大于1

[arr count]返回(NSUInteger),即typedef unsigned long NSUInteger;

所以NSUInteger不会有任何负数。值从0开始到某个最大值,它将像下面这样的循环

... | MAX-2 | MAX-1 | MAX | 0 | 1 | 2 | 3 | 4 | ...
           -1      -1    -1  -1  -1  -1  -1
So, the math is like 2-1 = 1
                     1-1 = 0
                     0-1 = MAX
                     0-2 = MAX-1 

最新更新