NSInteger
在32位平台上为32位,在64位平台上为64位。是否有NSLog
说明符始终与NSInteger
的大小相匹配?
设置
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:]
。
答案 0 :(得分:285)
更新回答:
使用当前的Xcode,您可以在所有体系结构上使用z
和t
修饰符来处理NSInteger
和NSUInteger
,而不会发出任何警告。
您希望%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。否则,每个编译都会创建一个单独的警告。