NSInteger myInt = 1804809223;
NSLog(@"%i", myInt); <====
上面的代码会产生错误:
Values of type "NSInteger" should not be used as format arguments: add an explicit cast to 'long' instead.
正确的NSLog
消息实际上是NSLog(@"%lg", (long) myInt);
如果我希望显示该值,为什么我必须将myInt的整数值转换为long?
答案 0 :(得分:192)
如果在OS X(64位)上进行编译,则会收到此警告,因为在该平台上NSInteger
被定义为long
并且是64位整数。另一方面,%i
格式适用于int
,即32位。因此格式和实际参数的大小不匹配。
由于NSInteger
是32位或64位,因此编译器建议,具体取决于平台
通常会将演员表添加到long
。
更新:由于iOS 7现在也支持64位,因此编译时可以收到相同的警告 对于iOS。
答案 1 :(得分:36)
如果您的格式说明符与您的数据类型匹配,则不必转换为任何内容。请参阅Martin R的答案,其中将本机类型NSInteger
定义为。
因此,在OS X 64位上,您可以编写如下的日志语句:
NSLog(@"%ld", myInt);
在iOS上你可以写:
NSLog(@"%d", myInt);
并且没有演员阵容都可以。
无论如何,至少在非UI代码中使用强制转换的一个原因是好的代码往往是跨平台移植的,如果你明确地转换变量,它将在32位和64位上完全编译:NSLog(@"%ld", (long)myInt);
这也有助于你的iOS代码过渡到64位,如果它来到iOS。或者当iOS和OS X合并在一起时。
请注意,这不仅适用于NSLog语句,它毕竟只是调试辅助工具,也适用于[NSString stringWithFormat:]
和朋友,它们是生产代码的合法元素。
答案 2 :(得分:22)
不要将NSInteger传递给NSLog,只需传递一个NSNumber即可。这将解决所有演员表并选择正确的字符串格式说明符。
NSNumber foo = @9000;
NSLog(@"foo: %@", foo);
NSInteger bar = 9001;
NSLog(@"bar: %@", @(bar));
它也适用于NSUIntegers而不必担心。 请参阅NSInteger and NSUInteger in a mixed 64bit / 32bit environment的答案
答案 3 :(得分:0)
在使用NSLog(@"%ld", (long)myInt);
时会一直发出警告,但在iOS 10中更改声明到long myInt = 1804809223;
后会停止警告。
答案 4 :(得分:-2)
OS X使用多种数据类型-NSInteger,NSUInteger,CGFloat和CFIndex-来提供在32位和64位环境中表示值的一致方法。在32位环境中,NSInteger和NSUInteger分别定义为int和unsigned int。在64位环境中,NSInteger和NSUInteger分别定义为long和unsigned long。为了避免根据平台使用不同的printf样式类型说明符,可以使用this link中显示的说明符来表示32位和64位环境。