一个关于NSUInteger的小细节

先看一段代码:

萌新经常会写出这样的代码:

1
2
3
4
5
// array 是一个数组,做一个遍历数组的操作
for (int i = 0; i < array.count - 1; i++) {
// 一些操作
NSLog(@"123");
}

乍一看好像没什么问题啊?其实不然,这里隐藏了一个很大的bug:当数组array为空数组时,循环体依然会执行,并且会执行到“天荒地老”。萌新一脸懵逼,甚至有点怀疑人生:joy:。

为什么会出现这种情况呢?

让我们一点点分析。

循环体能够执行说明满足了循环条件,那么问题就出在array.count - 1的身上了。

点进API文档,可以看到arraycount属性返回的是一个NSUInteger类型的值,也就是无符号长整型。当数组元素为空时,我们打印下array.count - 1的值,发现控制台输出:18446744073709551615ld,What?不应该是-1吗???

实际上,在计算机中,数字是用“补码”表示的:

正数的补码 = 原码 = 反码;
负数的补码 = 反码 (原码取反,最高位符号位不取反) +1 ;

64位操作系统的下,我们计算下-1的补码:
原码:
1000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0001
反码:
1111 1111 1111 1111 1111 1111 1111 1111
1111 1111 1111 1111 1111 1111 1111 1110
补码:
1111 1111 1111 1111 1111 1111 1111 1111
1111 1111 1111 1111 1111 1111 1111 1111

所以就得到了一个很大的十进制数:18446744073709551615ld

到这里问题就搞清楚了。解决办法也很简单,只需要做一次类型转换就可以了:

1
2
3
4
5
NSIteger n = array.count - 1;
for (int i = 0; i < n; i++) {
// 一些操作
NSLog(@"123");
}
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2021 bestdew
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信