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

Posted

技术标签:

【中文标题】NSInteger 和 NSUInteger 在混合的 64 位 / 32 位环境中【英文标题】:NSInteger and NSUInteger in a mixed 64bit / 32bit environment 【发布时间】:2013-12-19 18:19:07 【问题描述】:

我在 NSLog / NSAssert 等调用中有相当数量的字符串格式说明符,它们分别使用 %d%uNSInteger (= int on 32bit)NSUInteger (= unsigned int on 32bit) 类型。

将应用程序转换为 64 位时,这会发出警告(当然),因为 %ld %lu 预计现在变成了 longunsigned long 类型。

简单地转换格式说明符当然会在 32 位版本中引入反向警告。 因此,我看到的唯一没有警告的解决方案是使用 64 位说明符,并将 32 位构建中出现警告的任何地方都转换为 64 位值类型。

但我想知道是否有专门针对 NSIntegerNSUInteger 类型的格式说明符,无需强制转换即可在两种架构上工作?

【问题讨论】:

我们可以禁用警告吗? 【参考方案1】:

我认为最安全的方法是将它们装箱到 NSNumber 实例中。

NSLog(@"Number is %@", @(number)); // use the highest level of abstraction

由于tagged pointer 魔术,这种装箱通常不必创建新对象。

如果你真的不想使用NSNumber,你可以手动转换原始类型,就像其他人建议的那样:

NSLog(@"Number is %ld", (long)number); // works the same on 32-bit and 64-bit

【讨论】:

为什么这比投到 long 更“安全”? 如果您将NSUInteger 的显式转换插入unsigned long,但将其更改为NSInteger,您会得到不正确的负值行为而没有警告。 @() 保证在所有情况下都能正常工作。 @NikolaiRuhe:是的,我现在确实看到了优势。我仍然不愿意创建一个仅用于打印整数的对象,并且您会丢失一些功能(例如为十六进制输出指定宽度 %10d 或 %x )。但是,是的,对于调试,这是一个不错的选择。 @NikolaiRuhe,我认为标记指针很便宜(没有 malloc)。关于%10d 的好点。十六进制 - [NSData dataWithBytes:&number length:sizeof(number)] 怎么样?【参考方案2】:

您还可以在登录控制台时使用%zd (NSInteger) 和%tu (NSUInteger)。

NSInteger integer = 1;
NSLog(@"first number: %zd", integer);

NSUInteger uinteger = 1;
NSLog(@"second number: %tu", uinteger);

Also to be found here.

【讨论】:

+1 这应该是最好的。来自*** z:对于整数类型,导致 printf 需要一个 size_t 大小的整数参数。【参考方案3】:

没有,(很遗憾)没有直接对应NS(U)Integer的printf格式。 所以对于架构无关的代码,你必须将所有内容都转换为“long” 变体(正如 Xcode “Fix-it”所建议的那样):

NSInteger i = ...;
NSLog(@"%ld", (long)i);

我知道的唯一选择是来自Foundation types when compiling for arm64 and 32-bit architecture:

// In the precompiled header file:
#if __LP64__
#define NSI "ld"
#define NSU "lu"
#else
#define NSI "d"
#define NSU "u"
#endif

NSInteger i = ...;
NSLog(@"i=%"NSI, i);

使用预处理器宏(但即使该答案的作者也称其为 “不可否认的糟糕方法”)。

【讨论】:

不错。这就是 <inttypes.h> 对标准类型所做的。

以上是关于NSInteger 和 NSUInteger 在混合的 64 位 / 32 位环境中的主要内容,如果未能解决你的问题,请参考以下文章

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

int 或 NSInteger 到 NSUInteger 用于索引

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

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

NSInteger 类型

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