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
和 %u
与 NSInteger (= int on 32bit)
和 NSUInteger (= unsigned int on 32bit)
类型。
将应用程序转换为 64 位时,这会发出警告(当然),因为 %ld %lu
预计现在变成了 long
和 unsigned long
类型。
简单地转换格式说明符当然会在 32 位版本中引入反向警告。 因此,我看到的唯一没有警告的解决方案是使用 64 位说明符,并将 32 位构建中出现警告的任何地方都转换为 64 位值类型。
但我想知道是否有专门针对 NSInteger
和 NSUInteger
类型的格式说明符,无需强制转换即可在两种架构上工作?
【问题讨论】:
我们可以禁用警告吗? 【参考方案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