NSInteger与int、long的区别和联系
- 内置类型的发展
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对象介绍