判断条件中使用array.count的坑

问题

在判断条件中使用数组的count属性获取数量会有个坑,先看代码:

    NSArray *array = @[@"", @""];
    NSInteger left = -1;
    NSInteger per = 30;
    NSInteger count = array.count;
    if (left < per * count) {
        NSLog(@"YES");
    } else {
        NSLog(@"NO");
    }
    // console: YES

    
    if (left < per * array.count) {
        NSLog(@"YES");
    } else {
        NSLog(@"NO");
    }

    // console: NO
  • 第一个if的判断结果是正确的。
  • 第二个if的判断结果是错误的。

目前原因暂未查到,如有大佬知道烦请告知

原因

感谢朋友@DeveloperHZ 提了个醒,原因找到了。
因为比较条件中的array.countNSUInteger类型,所以比较条件右边的表达式per*array.count的计算结果其实是NSUInteger类型,NSInteger类型和NSUInteger类型做比较时会现将表达式中的类型都转换为NSUInteger类型。
其本质原因是c语言中有符号类型和无符号类型运算比较的问题,直接说结论:

  • 有符号数和无符号数相运算(加减乘除)时,结果的二进制表达式不受何种符号类型影响的,而计算结果的值取决于结果所需呈现的类型
  • 当表达式中存在有符号类型和无符号类型时,默认情况下(没有强制转换)表达式的值将转化为无符号类型

解决方法

平时在开发时如要做条件判断,除非确定所有数据的格式类型,否则尽量将表达式两边强制转换为同一类型(避免默认转换为无符号类型,结论第二条)或者先将两个比较条件赋值局部变量再进行进行比较(计算结果值取决于所需类型,结论第一条)
推荐写法:

    NSArray *array = @[@"", @""];
    NSInteger left = -1;
    NSInteger per = 30;

// 处理方法一
    NSInteger sum = per * array.count;
    if (left < sum) {
        NSLog(@"YES");
    } else {
        NSLog(@"NO");
    }

// 处理方法二
    if (left < (NSInteger)(per * array.count)) {
        NSLog(@"YES");
    } else {
        NSLog(@"NO");
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。