iOS小知识(四)-从NSUInteger谈起

409 阅读2分钟
我们先看一组简单的代码,猜一猜控制台会输出什么呢?
    NSInteger a = -1;
    NSArray *array = @[@"str"];
    if (a > array.count) {
        NSLog(@"测试1");
    }else{
        NSLog(@"测试2");
    }

答案是:

1892093-a8ed41a9ef6109ea.png 控制台为输出 “测试1”,也就是说if里面的判断,-1>1是成立的,这明显是反常识的,为什么if条件会成立的,我们继续往下看。

1892093-7f729e4040574d08.png 在CPU为64位情况下(iPhone5s及以后的机型,均为64位) NSInteger即为long类型 64位下 NSUInteger 即为 unsigned long 类型 64位下,long和unsigned long下所占字节均为8字节。 首先变量a是NSInteger类型,而NSArray的count属性,我们点进去去看,可以看到是NSUInteger类型(NSString的length类型同为NSUInteger),所以if里面的表达式本质就成为了long 和 unsigned long 进行数值比较。即有符号和无符号数的比较。 而编译器在判断有符号数和无符号数进行比较时,一律会将有符号数转化为无符号数。即将NSInteger类型的值-1转换为NSUInteger类型 那么,有符号数如何转化为无符号数呢?

在计算机内存存储的有符号数的最高位变为数据位,即有符号数转为无符号数。

在计算机中,数据是以补码的形式存在的。

原码:正数的原码是自己 补码:除符号位外,按位取反,然后+1 所以十进制的-1转成8个字节64位二进制后,为 1000 0000 0000 ... 0001 (共64位,首位为符号位1 表示为负数) 而实际上计算机存储的-1是它的补码 即: 1111 1111 1111 ... 1111 转成无符号数后,最高位的1不在表示符号位,而表示数据位。 64个1 即(2的64次方-1) 结果是 18446744073709551615 所以if里面的表达式-1 在转为无符号数以后,最后变成了:18446744073709551615 所以,就有了开头的那个结果。