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

Jes*_*and 29 c cocoa types objective-c

任何人都有专业知识来解释何时使用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
Run Code Online (Sandbox Code Playgroud)

小智 31

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

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

NSInteger si = -1;
NSUInteger ui = 1;
printf("%d\n", si < ui);
Run Code Online (Sandbox Code Playgroud)

原因是[si]变量被隐式转换为unsigned int!

请参阅CERT的安全编码站点,深入讨论这些"问题"以及如何解决这些问题.


Kri*_*ore 20

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


Car*_*rum 7

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

  • 我走了另一条道路:我总是使用NSUInteger,除非我需要负数.另外,你的意思是对象,而不是类; 传递类的原因很少,特别是传递NSDecimalNumber类的原因更少. (7认同)

Aar*_*nLS 5

我并不特别了解cocoa,但通常签名整数的唯一缺点是它们的最大值通常是unsigned int的一半.比如大约20亿而不是40亿的32位系统.一般情况下这并不是一个很大的区别,因为如果你处理接近20亿的价值,你可能会同样担心同样情况下最多40亿,因为它仍然非常接近溢出乘以2或3.

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

如果要强制执行仅正值,则可能首选未签​​名.

  • 如果您希望能够将变量初始化为"无效"值(例如-1),则有时会使用有符号整数,即使正常范围为正. (4认同)
  • 有趣的是,作为Objective C的替代品,Swift表示在可能的情况下始终使用带符号的数字.*来自docs*:仅当您特别需要与平台的本机字大小相同的无符号整数类型时才使用UInt.如果不是这种情况,则优选Int,即使已知要存储的值是非负的.Int对整数值的一致使用有助于代码互操作性,避免在不同数字类型之间进行转换,并匹配整数类型推断,如类型安全和类型推断中所述. (3认同)