何时使用NSInteger与int


344

NSInteger为iOS开发时应何时使用vs.int?我在Apple示例代码中看到,当将值作为参数传递给函数或从函数返回值时,它们会使用NSInteger(或NSUInteger)。

- (NSInteger)someFunc;...
- (void)someFuncWithInt:(NSInteger)value;...

但是在一个函数中,它们只是int用来跟踪值

for (int i; i < something; i++)
...

int something;
something += somethingElseThatsAnInt;
...

我读过(被告知)这NSInteger是在64位或32位环境中引用整数的一种安全方法,那么为什么要使用它int呢?

Answers:


322

NSInteger当您不知道代码可以在哪种处理器体系结构上运行时,通常需要使用它,因此由于某种原因,您可能想要最大可能的整数类型,在32位系统上,该类型仅是一个int,而在64 位系统上则为。系统是一个long

除非您特别要求NSInteger,否则我会坚持使用int/ 代替long

NSInteger/ NSUInteger被定义为typedef以下类型之一的* dynamic * s,它们的定义如下:

#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

关于应为每种类型使用的正确格式说明符,请参阅《字符串编程指南》中有关平台依赖项的部分


4
另外,除非您特别需要int或long int,否则我会说最好使用NSInteger。
v01d 2010年

4
@Shizam可能使用int甚至更适合long。也许您知道它不会超出某个范围,因此认为仅使用它会更节省内存int
Jacob Relkin 2010年

58
我不同意这个答案。我唯一要使用NSInteger的就是在指定它的API之间传递值。除此之外,它比int或long没有优势。至少对于int或long而言,您知道在printf或类似语句中使用哪种格式说明符。
JeremyP 2010年

3
如果在64b系统中工作时需要存储很长的时间并使用NSInteger,而其他用户使用32b系统会发生什么呢?您不会注意到失败,但是用户会注意到。
arielcamus 2012年

14
这是倒退。除非您有特殊原因,否则始终使用int。使用特定于平台的简单整数定义没有任何作用,但会使您的代码更难阅读。
Glenn Maynard

44

为什么要使用int

Apple使用int它是因为对于循环控制变量(仅用于控制循环迭代),int数据类型在数据类型大小和它可以为循环保留的值方面都很好。此处无需依赖平台的数据类型。对于循环控制变量int,大多数情况下,甚至16位也可以。

Apple使用NSInteger函数返回值或函数自变量,因为在这种情况下,数据类型[size]很重要,因为您对函数所做的工作是与其他程序或其他代码段通信/传递数据。看到我何时应该使用NSInteger vs int的答案在你的问题本身...

他们[Apple] 在将值作为参数传递给函数从函数返回值使用NSInteger(或NSUInteger)。


32

OS X是“ LP64”。这意味着:

int 始终为32位。

long long 始终是64位。

NSInteger并且long总是指针大小。这意味着它们在32位系统上为32位,在64位系统上为64位。

NSInteger的存在,究其原因是因为许多旧的API使用不当int,而不是long持有指针大小的变量,这意味着该API的必须的变化,从intlong其64位版本。换句话说,API将具有不同的功能签名,具体取决于您是针对32位还是64位体系结构进行编译。 NSInteger打算使用这些旧版API掩盖此问题。

在新代码中,int如果需要32位变量,long long需要64位整数longNSInteger需要指针大小的变量,请使用。


25
历史已经存在,但建议却很糟糕。如果您需要32位变量,请使用int32_t。如果需要64位整数,请使用int64_t。如果需要指针大小的变量,请使用intptr_t
斯蒂芬·佳能2010年

5
Stephen,您的建议是永远不要使用int,long或NSInteger?
达伦(Darren)2010年

7
不,我的建议是,如果需要已知固定大小的整数类型,请不要使用它们。该<stdint.h>类型用于这一目的存在。
斯蒂芬·佳能2010年

3
Stephen,我的回答是回答“何时使用NSInteger vs int”这个问题,而不是“什么是32位整数的跨平台类型名称”。如果有人试图在NSInteger和int之间做出选择,他们可能会知道他们在支持的平台上有多大。
达伦

1
另请注意,LP64这并不保证long long是64位。一个LP64平台可以选择long long使用128位整数。
斯蒂芬·佳能2010年

26

如果您深入研究NSInteger的实现:

#if __LP64__
typedef long NSInteger;
#else
typedef int NSInteger;
#endif

简而言之,NSInteger typedef为您做了一个步骤:如果体系结构是32位,则使用int;如果体系结构是64位,则使用long。使用NSInteger,您无需担心程序正在运行的体系结构。


14
您确实需要担心,因为NSInteger的正确格式说明符取决于体系结构。
JeremyP 2010年

根据Apple手册,最简单的方法是将值转换为最大的数字类型long long。因此,所有数字类型都将使用相同的类型说明符。
埃尼尔(Eonil)2012年

6
现在,最简单的格式化方法是将它们装箱NSLog("%@", @(1123));
Eonil

1
您也可以投射它:NSLog("%li", (long)theNSInteger);
丹尼尔(Daniel)

演员让我伤心
tomalbrc

9

如果需要将它们与常量值(例如NSNotFound或NSIntegerMax)进行比较,则应使用NSIntegers,因为这些值在32位和64位系统上会有所不同,因此索引值,计数等类似:请使用NSInteger或NSUInteger。

在大多数情况下,使用NSInteger不会造成任何伤害,只是它占用的内存是原来的两倍。内存影响很小,但是如果您一次有大量的数字在浮动,那么使用整数可能会有所不同。

如果您确实使用NSInteger或NSUInteger,则在使用格式字符串时,您将希望将它们转换为长整数或无符号长整数,因为如果您尝试注销NSInteger时就好像它具有已知长度,则新的Xcode功能会返回警告。同样,将它们发送到类型为int的变量或参数时,也应小心,因为您可能会在过程中失去一些精度。

总的来说,如果您不希望一次存储数十万个内存,那么使用NSInteger会比不断担心两者之间的差异要容易得多。


9

从目前(2014年9月)开始,NSInteger/CGFloat如果您还为arm64构建应用程序,则建议与iOS API等交互时使用。这是因为,当您使用可能会得到意想不到的效果floatlongint类型。

示例:浮点/双点与CGFLOAT

作为示例,我们采用UITableView委托方法tableView:heightForRowAtIndexPath:

在仅32位应用程序中,如果这样编写,它将可以正常工作:

-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44;
}

float是32位值,您要返回的44是32位值。但是,如果我们在64位arm64体系结构中编译/运行同一段代码,则44将是64位值。如果期望的值为32位,则返回64位的值会产生意外的行高。

您可以使用以下CGFloat类型解决此问题

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44;
}

此类型float在32位环境中表示32位,double在64位环境中表示64位。因此,使用此类型时,无论编译/运行时环境如何,该方法将始终接收预期的类型。

对于期望整数的方法也是如此。此类方法int在32位环境中期望值为32位,而在64位环境中期望值long为64位。您可以通过使用基于编译/运行时环境NSIntegerintlong基于的类型来解决这种情况。


如果我知道这个特定变量的值不能包含大数值,那么我该使用int怎么办。它在64位环境中都能正常工作吗?我认为它应该也一样,我还没有看到一个像这样的循环:for(INT I = 0;我<10; i ++在)做任何错误的行为,无论环境,它在运行。
沙勒拉吉

@Chanchal Raj只要没有强制转换或转换为其他类型或涉及该变量的第三方类和方法的使用/重写,可以使用int代替NSInteger。
Leon Lucardie

9

在iOS上,当前使用int或都没有关系NSInteger。如果/当iOS移至64位时,这将更为重要。

简而言之,NSIntegers是int32位代码中的s(因此是32位长),而longs是64位代码上的longs(64位代码中的s是64位宽,而32位代码中的32位)。使用NSInteger而不是的最可能原因long是不破坏现有的32位代码(使用ints)。

CGFloat具有相同的问题:在32位(至少在OS X上)是float;在64位,它的double

更新:随着iPhone 5s,iPad Air,带有Retina的iPad Mini和iOS 7的推出,您现在可以在iOS上构建64位代码。

更新2:此外,使用NSIntegers可以提高Swift代码的互操作性。


0

int = 4字节(固定大小,与架构师无关)NSInteger =取决于架构师的大小(例如4字节架构师= 4字节NSInteger大小)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.