NSInteger 的 NSLog/printf 说明符? ?

NSInteger在32位平台上是32位,在64位平台上是64位。是否有一个 NSLog说明符总是匹配 NSInteger的大小?

设置

  • Xcode 3.2.5
  • Lvm 1.6编译器 (这很重要; gcc 不这样做)
  • 打开 GCC_WARN_TYPECHECK_CALLS_TO_PRINTF

这让我很伤心:

#import <Foundation/Foundation.h>


int main (int argc, const char * argv[]) {
@autoreleasepool {
NSInteger i = 0;
NSLog(@"%d", i);
}
return 0;
}

对于32位代码,我需要 %d说明符。但是如果我使用 %d说明符,我在编译64位时会得到一个警告,建议我改用 %ld

如果我使用 %ld来匹配64位大小,当编译32位代码时,我会得到一个警告,建议我使用 %d代替。

如何同时修复这两个警告? 是否有一个说明符,我可以使用它们中的任何一个?

这也会影响 [NSString stringWithFormat:][[NSString alloc] initWithFormat:]

80428 次浏览

更新答案:

您可以在所有体系结构上使用 zt修饰符来处理 NSIntegerNSUInteger,而无需警告。

您希望将 %zd用于有符号,将 %tu用于无符号,将 %tx用于十六进制。

这些信息是由 Greg Parker提供的。


原答案:

官方建议的方法使用 %ld作为说明符,并将实际参数强制转换为 long

格式化程序来自标准的 UNIX/POSIX printf 函数。对于 未签名的长期使用 % lu,长时间使用% ld,长时间使用% ld,对于 未签名长期长期使用 % llu。在控制台上尝试 man printf,但在 Mac 上它是不完整的。Linux 手册页的 http://www.manpages.info/linux/sprintf.3.html更加明确

这两个警告只能通过 NSLog (@“% lu”,(无符号长度) arg)修复; 结合强制转换,因为代码将在 iOS 中以32位和64位编译。否则,每次编译都会创建一个单独的警告。

接受的答案是绝对合理的,它是标准一致的,正确的。唯一的问题是它不再工作了,这完全是苹果的错。

格式% zd 是 size _ t 和 ssize _ t 的 C/C + + 标准格式。与 NSInteger 和 NSUInteger 一样,size _ t 和 ssize _ t 在32位系统上是32位,在64位系统上是64位。这就是为什么打印 NSInteger 和 NSUInteger 使用% zd 工作。

然而,NSInteger 和 NSUInteger 在64位系统上定义为“ long”,在32位系统上定义为“ int”(即64位对32位)。现在,size _ t 在所有系统上都定义为“ long”,的大小与 NSInteger (64位或32位)相同,但是类型不同。要么苹果的警告已经改变(因此它不允许传递错误的类型到 printf,即使它有正确的位数) ,要么 size _ t 和 ssize _ t 的底层类型已经改变。我不知道是哪一个,但是% zd 已经停止工作一段时间了。现在有一种 没有格式,可以在32位和64位系统上在没有警告的情况下打印 NSInteger。

因此,您唯一可以做的事情是: 使用% ld,将您的值从 NSInteger 强制转换为 long,或者从 NSUInteger 强制转换为 unsignedlong。

一旦不再为32位构建,就可以直接使用% ld,不需要任何强制类型转换。