美文网首页Objective-C
NSInteger与int、long的区别和联系

NSInteger与int、long的区别和联系

作者: MichaelLedger | 来源:发表于2018-03-08 00:17 被阅读37次
    • 内置类型的发展

    C语言开始时只有char(8位)和int(16位)两种,后来随着发展又加入了short(16位)和long(32位),此时,int可以是16位或者32位,依赖于平台和后续的兼容性。再后来当64位出现时,long long(64位)又被添加进来,为了进行规范,对较小的一些类型的范围就有了一些调整,逐渐稳定为int32位,long可以有多种定义,可以是32位,也可以是64位。

    • 在C语言中,double、long、unsigned、int、char类型数据所占字节数

    和机器字长及编译器有关系,所以,int、long int、short int的宽度都可能随编译器而异。

    但有几条铁定的原则(ANSI/ISO制订的):

    1. sizeof(short int)<=sizeof(int) 
    2. sizeof(int)<=sizeof(long int) 
    3. short int至少应为16位(2字节) 
    4. long int至少应为32位(4字节)
    

    unsigned 是无符号的意思

    例如:
    16位编译器
    char :1个字节
    char*(即指针变量): 2个字节
    short int : 2个字节
    int: 2个字节
    unsigned int : 2个字节
    float: 4个字节
    double: 8个字节
    long: 4个字节
    long long: 8个字节
    unsigned long: 4个字节

    32位编译器

    char :1个字节
    char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
    short int : 2个字节
    int: 4个字节
    unsigned int : 4个字节
    float: 4个字节
    double: 8个字节
    long: 4个字节
    long long: 8个字节
    unsigned long: 4个字节

    64位编译器
    char :1个字节
    char*(即指针变量): 8个字节
    short int : 2个字节
    int: 4个字节
    unsigned int : 4个字节
    float: 4个字节
    double: 8个字节
    long: 8个字节
    long long: 8个字节
    unsigned long: 8个字节

    • NSInteger& NSUInteger

    #import <objc/NSObjCRuntime.h>源码中对NSInteger和NSUInteger的定义如下:

    /*  NSObjCRuntime.h
        Copyright (c) 1994-2012, Apple Inc. All rights reserved.
    */
    
    #ifndef _OBJC_NSOBJCRUNTIME_H_
    #define _OBJC_NSOBJCRUNTIME_H_
    
    #include <TargetConditionals.h>
    #include <objc/objc.h>
    
    #if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
    typedef long NSInteger;
    typedef unsigned long NSUInteger;
    #else
    typedef int NSInteger;
    typedef unsigned int NSUInteger;
    #endif
    
    #define NSIntegerMax    LONG_MAX
    #define NSIntegerMin    LONG_MIN
    #define NSUIntegerMax   ULONG_MAX
    
    #define NSINTEGER_DEFINED 1
    
    #ifndef NS_DESIGNATED_INITIALIZER
    #if __has_attribute(objc_designated_initializer)
    #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
    #else
    #define NS_DESIGNATED_INITIALIZER
    #endif
    #endif
    
    #endif
    

    原来在苹果的api实现中,NSInteger是一个封装,它会识别当前操作系统的位数,自动返回最大的类型。
    32位系统中NSInteger为int;64位系统中NSInteger为long。

     You usually want to use NSInteger when you don't know what kind of processor architecture your code might run on, so you may for some reason want the largest possible int type, which on 32 bit systems is just an int, while on a 64-bit system it's a long.
    
    • 取值范围
    //32bit
    unsigned int 0~4294967295 
    int -2147483648~2147483647 
    unsigned long 和int一样
    long 和int一样
    long long的最大值:9223372036854775807
    long long的最小值:-9223372036854775808
    unsigned long long的最大值:1844674407370955161
    __int64的最大值:9223372036854775807
    __int64的最小值:-9223372036854775808
    unsigned __int64的最大值:18446744073709551615
    
    //64bit
    unsigned int 0~4294967295 
    int -2147483648~2147483647 
    unsigned long 和 unsigned long long一样
    long 和long long一样
    long long的最大值:9223372036854775807
    long long的最小值:-9223372036854775808
    unsigned long long的最大值:1844674407370955161
    __int64的最大值:9223372036854775807
    __int64的最小值:-9223372036854775808
    unsigned __int64的最大值:18446744073709551615
    
    • 在32位系统中

    int 占4个字节
    long 占4个字节
    NSInteger 是int的别名,占4个字节
    long long 占8个字节
    int32_t 是int的别名,占4个字节
    int64_t 是long long的别名,占8个字节

    • 在64位系统中

    int 占4个字节
    long 占8个字节
    NSInteger 是long的别名,占8个字节
    long long 占8个字节
    int32_t 是int的别名,占4个字节
    int64_t 是long long的别名,占8个字节

    • 使用注意⚠️

    objective-c里,苹果的官方文档中总是推荐用NSInteger或者是NSUInteger,这样就不用考虑设备是32位还是64位了。

    NSUInteger是无符号的,即没有负数,NSInteger是有符号的,所以NSUInteger类型不能给它赋负值。

    比如以下这段代码,a=-1的时候,是能进入循环的。

    //64-bit system
    NSUInteger a = -1; 
    for(int i=0;i<a;i++){    
        NSLog(@"%d,%lu",i,(unsigned long)a);
        break;
    }
    

    输出:0,18446744073709551615
    这时a的值其实等于18446744073709551615(64位系统中)

    还有NSUInteger和NSInteger和int都是基础类型,是不能放入NSArray中的,需要转换成NSNumber,应为NSNumber是类,NSArray中只能放入类。

    NSNumber是NSValue的一个子类,它是一个对象来存储数字值包括bool型
    
    1. 提供了一系列的方法来存储char a signed or unsigned char, short int, int, long int, long long int, float, or double or as a BOOL
    2. 它提供了一个compare:方法来决定两个NSNumber对象的排序;
    

    用以下NSNumber的类方法转即可

    (NSNumber *) numberWithChar: (char) value;
    (NSNumber *) numberWithInt: (int) value;
    (NSNumber *) numberWithFloat: (float) value;
    (NSNumber *) numberWithBool: (BOOL) value;
    

    或者使用@简写

    @()代表NSNumber对象
    @""代表NSString对象
    @[]代表NSArray对象
    @{}代表NSDictionary对象
    

    将基本类型数据封装到NSNumber中后,就可以通过下面的实例方法重新获取它:

    - (char)charValue;
    - (int)intValue;
    - (float)floatValue;
    - (BOOL)boolValue;
    - (NSString *)stringValue;
    

    由于long和NSInteger的字节数变了,所以在兼容的时候可能会导致溢出

    对于一个11位的整数,它在64位系统中使用NSInteger或者long类型,是可以正常存储的;如果是在32位系统中,它就溢出了!

    所以要保证某些较大的整数可以正常使用的话,就需要使用long long或者int64_t这样的类型

    另外在类型转换的时候
    例如 int64_t转换成NSInteger,在64位系统中是正常的
    但在32位系统中就可能会导致溢出

    参考:
    int和NSInteger和long区别
    iOS下int long longlong的取值范围
    iOS int long NSInteger 入门与兼容问题讲解,让你秒懂
    为什么long和int都是4字节
    在C语言中,double、long、unsigned、int、char类型数据所占字节数
    iOS7----64位与32位 对比 数据类型
    iOS-NSNumber对象介绍

    相关文章

      网友评论

        本文标题:NSInteger与int、long的区别和联系

        本文链接:https://www.haomeiwen.com/subject/kmfefftx.html