145
NSInteger myInt = 1804809223;
NSLog(@"%i", myInt); <==== 

The code above produces an error:

Values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead

The corrected NSLog message is actually NSLog(@"%lg", (long) myInt);. Why do I have to convert the integer value of myInt to long if I want the value to display?

4

5 回答 5

194

如果您在 OS X(64 位)上编译,则会收到此警告,因为在该平台NSInteger上定义为long64 位整数。%i另一方面,格式是 for ,int它是 32 位的。所以格式和实际参数大小不匹配。

由于NSInteger是 32 位还是 64 位,取决于平台,编译器long一般建议添加强制转换。

更新:由于 iOS 7 现在也支持 64 位,因此在为 iOS 编译时会收到相同的警告。

于 2013-04-18T06:43:36.087 回答
39

如果您的格式说明符与您的数据类型匹配,则不必强制转换为任何内容。NSInteger有关如何根据本机类型定义的详细信息,请参阅 Martin R 的答案。

因此,对于旨在为 64 位环境构建的代码,您可以像这样编写日志语句:

NSLog(@"%ld",  myInt); 

而对于 32 位环境,您可以编写:

NSLog(@"%d",  myInt); 

没有演员表,这一切都可以工作。

无论如何使用强制转换的一个原因是好的代码倾向于跨平台移植,如果你明确地强制转换你的变量,它将在 32 位和 64 位上编译干净:

NSLog(@"%ld",  (long)myInt);

请注意,这不仅适用于 NSLog 语句,毕竟它们只是调试辅助工具,而且适用[NSString stringWithFormat:]于各种派生消息,它们是生产代码的合法元素。

于 2013-04-18T07:29:22.327 回答
22

无需将 NSInteger 传递给 NSLog,只需传递 NSNumber。这将绕过所有强制转换并选择正确的字符串格式说明符。

NSNumber foo = @9000;
NSLog(@"foo: %@", foo);
NSInteger bar = 9001;
NSLog(@"bar: %@", @(bar));

它也适用于 NSUIntegers 而不必担心。在混合 64 位/32 位环境中查看对 NSInteger 和 NSUInteger 的回答

于 2014-01-30T11:15:24.933 回答
0

它在使用时保持警告,但在 iOS 10 中NSLog(@"%ld", (long)myInt);更改声明后停止警告。long myInt = 1804809223;

于 2016-06-23T17:44:48.197 回答
-2

OS X 使用多种数据类型——NSInteger、NSUInteger、CGFloat 和 CFIndex——来提供在 32 位和 64 位环境中表示值的一致方法。在 32 位环境中,NSInteger 和 NSUInteger 分别定义为 int 和 unsigned int。在 64 位环境中,NSInteger 和 NSUInteger 分别定义为 long 和 unsigned long。为避免需要根据平台使用不同的 printf 样式类型说明符,您可以 将此链接中显示的说明符用于 32 位和 64 位环境。

于 2016-03-17T11:38:16.837 回答