NSInteger的NSLog / printf说明符?

时间:2010-12-10 01:58:25

标签: objective-c cocoa 32bit-64bit nslog nsinteger

NSInteger在32位平台上为32位,在64位平台上为64位。是否有NSLog说明符始终与NSInteger的大小相匹配?

设置

  • Xcode 3.2.5
  • llvm 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:]

3 个答案:

答案 0 :(得分:285)

更新回答:

使用当前的Xcode,您可以在所有体系结构上使用zt修饰符来处理NSIntegerNSUInteger,而不会发出任何警告。

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

此信息来自Greg Parker


原始答案:

official recommended approach是使用%ld作为您的说明符,并将实际参数转换为long

答案 1 :(得分:2)

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

格式%zd是size_t和ssize_t的C / C ++标准格式。像NSInteger和NSUInteger一样,size_t和ssize_t在32位系统上为32位,在64位系统上为64位。这就是使用%zd打印NSInteger和NSUInteger起作用的原因。

但是,在64位系统上,NSInteger和NSUInteger被定义为“长”,而在32位系统(64位与32位)上,NSInteger和NSUInteger被定义为“ int”。今天,在所有系统上,size_t都定义为“ long”,其 的大小与NSInteger相同(64位或32位),但是类型不同。 Apple的警告已更改(因此,即使其位数正确,也不允许将错误的类型传递给printf),或者size_t和ssize_t的基础类型已更改。我不知道是哪一个,但%zd前一段时间停止了工作。今天,在32位和64位系统上,没有 no 格式可以打印NSInteger而不发出警告。

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

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

答案 2 :(得分:0)

格式化程序来自标准的UNIX / POSIX printf函数。使用%lu 表示 unsigned long ,使用%ld表示long,%lld表示long long,%llu 表示 unsigned long long < / strong>即可。在控制台上尝试man printf,但在Mac上它是不完整的。 linux联机帮助页更明确http://www.manpages.info/linux/sprintf.3.html

两个警告只能由NSLog修复(@&#34;%lu&#34;,(unsigned long)arg);结合演员阵容,因为代码将在32位和64位编译为iOS。否则,每个编译都会创建一个单独的警告。