为什么NSIntegervariables在作为格式参数使用时必须转换为long?
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,如果我想要显示的值?
如果您在OS X(64位)上编译,则会得到此警告,因为在该平台上, NSInteger
被定义为long
并且是64位整数。 另一方面, %i
格式是32位的int
。 所以格式和实际参数大小不符。
由于NSInteger
是32位或64位的,因此根据平台的不同,编译器build议一般添加一个强制转换。
更新:由于iOS 7现在也支持64位,所以在为iOS编译时可以得到相同的警告。
如果格式说明符符合您的数据types,则不必转换为任何内容。 请参阅Martin R的答案,将NSInteger
定义为本机types。
所以在OS X 64位上,你可以写下你的日志语句:
NSLog(@"%ld", myInt);
而在iOS上,你可以写:
NSLog(@"%d", myInt);
这一切都将工作,没有施放。
无论如何,至less在非UI代码中使用强制转换的一个原因是好的代码倾向于跨平台移植,如果你显式地转换你的variables,它将在32位和64位上干净地编译:
NSLog(@"%ld", (long)myInt);
这也将帮助你的iOS代码过渡到64位,如果它来到iOS。 或者当iOS和OS X合并在一起。
并注意到这不仅仅是NSLog语句,毕竟它只是debugging帮助,而且也是[NSString stringWithFormat:]
和朋友,它们是生产代码的合法元素。
而不是传递NSInteger到NSLog,只是传递一个NSNumber。 这将绕过所有的演员,并select正确的string格式说明符。
NSNumber foo = @9000; NSLog(@"foo: %@", foo); NSInteger bar = 9001; NSLog(@"bar: %@", @(bar));
它也适用于NSUIntegers,而不必担心这一点。 在混合的64位/ 32位环境中查看NSInteger和NSUInteger的答案
它使用NSLog(@"%ld", (long)myInt);
保持警告NSLog(@"%ld", (long)myInt);
,但更改声明后停止警告long myInt = 1804809223;
在iOS 10中。
OS X使用多种数据types(NSInteger,NSUInteger,CGFloat和CFIndex)来提供在32位和64位环境中表示值的一致方法。 在32位环境中,NSInteger和NSUInteger分别定义为int和unsigned int。 在64位环境中,NSInteger和NSUInteger分别定义为long和unsigned long。 为了避免需要根据平台使用不同的printf样式types说明符,可以使用此链接中显示的说明符适用于32位和64位环境。