NSUInteger vs NSInteger,int vs unsigned,以及类似情况

Posted

技术标签:

【中文标题】NSUInteger vs NSInteger,int vs unsigned,以及类似情况【英文标题】:NSUInteger vs NSInteger, int vs unsigned, and similar cases 【发布时间】:2011-02-03 04:09:34 【问题描述】:

任何人都有专业知识来解释何时使用 NSUInteger 以及何时使用 NSInteger?

我见过 Cocoa 方法返回 NSInteger,即使在返回值总是无符号的情况下也是如此。

根本原因是什么?如果我们要表示负值,NSInteger 或 int 是否严格限制?

来自 NSObjCRuntime.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

【问题讨论】:

【参考方案1】:

在处理 NSUInteger 与 NSInteger 时,您还应该了解整数转换规则:

例如,以下片段返回 0(假),尽管您希望它打印 1(真):

NSInteger si = -1;
NSUInteger ui = 1;
printf("%d\n", si < ui);

原因是 [si] 变量被隐式转换为无符号整数!

请参阅CERT's Secure Coding site,深入讨论这些“问题”以及如何解决这些问题。

【讨论】:

【参考方案2】:

默认情况下,假定一个整数是有符号的。换句话说,编译器假定将调用一个整数变量来存储负数或正数。这限制了范围可以在任一方向上达到的范围。例如,32 位 int 的范围为 4,294,967,295。实际上,由于该值可能是正数或负数,因此范围实际上是 -2,147,483,648 到 +2,147,483,647。如果我们知道永远不会调用变量来存储负值,我们可以将其声明为无符号,从而将(正)范围扩展到 0 到 +4,294,967,295。所以我想说,当你知道你有一个受限的输出范围时,使用 NSInteger 是可以的。如果我需要返回非常大的仅正数,我个人会使用 NSUInteger

【讨论】:

不错的答案和我需要知道的:) 如果我想存储 -4,294,967,295 怎么办?那我就不能用 NSInteger 了吗? @Nil long long int:-9,223,372,036,854,775,807 到 9,223,372,036,854,775,807 unsigned long long int:0 到 18,446,744,073,709,551,615。在您的帐户中拥有相当多的金额:D【参考方案3】:

如果您的方法具有适当限制的输出范围,您不妨使用NSInteger,因为它更易于输入。正如您所说,如果您需要返回负数,NSInteger 是镇上唯一的游戏;如果我出于某种原因需要返回真的大数字,我只会使用NSUInteger

【讨论】:

对于更大的数字,使用 NSDecimalNumber 38 位以 10 为底的精度。 +1,@codewarrior,但前提是你可以通过课程。 我走另一条路:我一直使用 NSUInteger,除非我需要负数。另外,您的意思是对象,而不是类;传递类的理由很少,专门传递 NSDecimalNumber 类的理由就更少了。 我想这真的取决于我们的需求。【参考方案4】:

我不具体了解可可,但通常有符号整数的唯一缺点是它们通常具有最大值的一半作为无符号整数。例如大约 20 亿而不是 32 位系统的 40 亿。一般来说,这没什么大的区别,因为如果您处理的值接近 20 亿,您可能会担心在相同情况下的最大值为 40 亿,因为它仍然非常接近溢出,只有2 或 3 的乘法。

通常首选有符号整数,因为有符号整数具有额外的灵活性和事实,即有符号整数几乎可以在所有场景中使用,无符号整数可以加上它不能在需要负数的所有其他场景中使用。

如果您只想强制执行正值,则可能首选无符号。

【讨论】:

我添加了NSInteger和NSUInteger的定义。 如果您希望能够将变量初始化为“无效”值(例如 -1),即使正常范围为正数,有时也会使用有符号整数。 有趣的是,Objective C 的替代品 Swift 说尽可能使用带符号的数字。 来自文档:仅当您特别需要与平台的原生字长相同大小的无符号整数类型时才使用 UInt。如果不是这种情况,则首选 Int,即使要存储的值已知为非负数。将 Int 一致地用于整数值有助于代码互操作性,避免在不同数字类型之间进行转换,并匹配整数类型推断,如类型安全和类型推断中所述。 为了使用的一致性,我同意这一点

以上是关于NSUInteger vs NSInteger,int vs unsigned,以及类似情况的主要内容,如果未能解决你的问题,请参考以下文章

int 或 NSInteger 到 NSUInteger 用于索引

int、NSInteger 和 NSUInteger 的区别

NSNumber 为 0 转换为 NSInteger/NSUInteger 变为 nil

NSInteger 和 NSUInteger 在混合的 64 位 / 32 位环境中

如何在目标 C 中将 NSInteger 值转换为 int 值? [复制]

NSInteger 类型