为什么NSInteger变量在用作格式参数时必须转换为long ?

时间:2022-09-11 19:47:56
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 correct 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?

正确的NSLog消息实际上是NSLog(@“%lg”,(long) myInt);如果我想要显示值,为什么要将myInt的整数值转换为long ?

5 个解决方案

#1


183  

You get this warning if you compile on OS X (64-bit), because on that platform NSInteger is defined as long and is a 64-bit integer. The %i format, on the other hand, is for int, which is 32-bit. So the format and the actual parameter do not match in size.

如果在OS X(64位)上编译,就会得到这个警告,因为在这个平台上,NSInteger被定义为long,并且是一个64位整数。另一方面,%i格式是用于int,这是32位。因此格式和实际参数在大小上不匹配。

Since NSInteger is 32-bit or 64-bit, depending on the platform, the compiler recommends to add a cast to long generally.

由于NSInteger是32位或64位的,这取决于平台,因此编译器通常建议向long添加类型转换。

Update: Since iOS 7 supports 64-bit now as well, you can get the same warning when compiling for iOS.

更新:由于iOS 7现在也支持64位,所以在为iOS编译时也可以得到相同的警告。

#2


35  

You don't have to cast to anything if your format specifiers match your data types. See Martin R's answer for which native types NSInteger is defined as.

如果格式说明符与数据类型相匹配,您就不必强制转换任何内容。参见Martin R的答案,NSInteger的本地类型定义为。

So on OS X 64-bit, you can write your log statements like this:

所以在OS X 64位上,你可以这样写你的日志语句:

NSLog(@"%ld",  myInt); 

while on iOS you can write:

在iOS上,你可以这样写:

NSLog(@"%d",  myInt); 

and it will all work without casts.

而且所有的工作都不会被强制执行。

One reason to use casts anyway, at least in the non-UI code, is that good code tends to be ported across platforms, and if you cast your variables explicitly it will compile cleanly on both 32 and 64 bit:

使用类型转换(至少在非ui代码中)的一个原因是,好的代码倾向于跨平台移植,如果您显式地转换变量,它将在32位和64位上编译得很干净:

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

This will also help your iOS code in a transition to 64 bit, should it ever come to iOS. Or when iOS and OS X get merged together down the line.

这也将帮助你的iOS代码过渡到64位,它是否应该出现在iOS中。或者当iOS和OS X合并到一起的时候。

And notice this goes not just for NSLog statements, which are just debugging aids after all, but also for [NSString stringWithFormat:] and friends, which are legitimate elements of production code.

注意,这不仅仅适用于NSLog语句,它毕竟是调试辅助工具,也适用于[NSString stringWithFormat:]和朋友,它们是生产代码的合法元素。

#3


22  

Instead of passing an NSInteger to NSLog, just pass an NSNumber. This will get around all the casts and choosing the right string format specifier.

不要将一个NSInteger传递给NSLog,只需传递一个NSNumber。这将绕过所有的类型转换,并选择正确的字符串格式说明符。

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

It also works for NSUIntegers without having to worry about that. See answer to NSInteger and NSUInteger in a mixed 64bit / 32bit environment

它也适用于NSUIntegers,不用担心这个问题。在混合的64位/ 32位环境中,请参见对NSInteger和NSUInteger的回答

#4


0  

It keeps warning while using NSLog(@"%ld", (long)myInt);, but stops warning after change declaration to long myInt = 1804809223; in iOS 10.

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

#5


-2  

OS X uses several data types—NSInteger, NSUInteger,CGFloat, and CFIndex—to provide a consistent means of representing values in 32- and 64-bit environments. In a 32-bit environment, NSInteger and NSUInteger are defined as int and unsigned int, respectively. In 64-bit environments, NSInteger and NSUInteger are defined as long and unsigned long, respectively. To avoid the need to use different printf-style type specifiers depending on the platform, you can use the specifiers shown in this link for both 32 bit and 64 bit environment.

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

#1


183  

You get this warning if you compile on OS X (64-bit), because on that platform NSInteger is defined as long and is a 64-bit integer. The %i format, on the other hand, is for int, which is 32-bit. So the format and the actual parameter do not match in size.

如果在OS X(64位)上编译,就会得到这个警告,因为在这个平台上,NSInteger被定义为long,并且是一个64位整数。另一方面,%i格式是用于int,这是32位。因此格式和实际参数在大小上不匹配。

Since NSInteger is 32-bit or 64-bit, depending on the platform, the compiler recommends to add a cast to long generally.

由于NSInteger是32位或64位的,这取决于平台,因此编译器通常建议向long添加类型转换。

Update: Since iOS 7 supports 64-bit now as well, you can get the same warning when compiling for iOS.

更新:由于iOS 7现在也支持64位,所以在为iOS编译时也可以得到相同的警告。

#2


35  

You don't have to cast to anything if your format specifiers match your data types. See Martin R's answer for which native types NSInteger is defined as.

如果格式说明符与数据类型相匹配,您就不必强制转换任何内容。参见Martin R的答案,NSInteger的本地类型定义为。

So on OS X 64-bit, you can write your log statements like this:

所以在OS X 64位上,你可以这样写你的日志语句:

NSLog(@"%ld",  myInt); 

while on iOS you can write:

在iOS上,你可以这样写:

NSLog(@"%d",  myInt); 

and it will all work without casts.

而且所有的工作都不会被强制执行。

One reason to use casts anyway, at least in the non-UI code, is that good code tends to be ported across platforms, and if you cast your variables explicitly it will compile cleanly on both 32 and 64 bit:

使用类型转换(至少在非ui代码中)的一个原因是,好的代码倾向于跨平台移植,如果您显式地转换变量,它将在32位和64位上编译得很干净:

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

This will also help your iOS code in a transition to 64 bit, should it ever come to iOS. Or when iOS and OS X get merged together down the line.

这也将帮助你的iOS代码过渡到64位,它是否应该出现在iOS中。或者当iOS和OS X合并到一起的时候。

And notice this goes not just for NSLog statements, which are just debugging aids after all, but also for [NSString stringWithFormat:] and friends, which are legitimate elements of production code.

注意,这不仅仅适用于NSLog语句,它毕竟是调试辅助工具,也适用于[NSString stringWithFormat:]和朋友,它们是生产代码的合法元素。

#3


22  

Instead of passing an NSInteger to NSLog, just pass an NSNumber. This will get around all the casts and choosing the right string format specifier.

不要将一个NSInteger传递给NSLog,只需传递一个NSNumber。这将绕过所有的类型转换,并选择正确的字符串格式说明符。

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

It also works for NSUIntegers without having to worry about that. See answer to NSInteger and NSUInteger in a mixed 64bit / 32bit environment

它也适用于NSUIntegers,不用担心这个问题。在混合的64位/ 32位环境中,请参见对NSInteger和NSUInteger的回答

#4


0  

It keeps warning while using NSLog(@"%ld", (long)myInt);, but stops warning after change declaration to long myInt = 1804809223; in iOS 10.

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

#5


-2  

OS X uses several data types—NSInteger, NSUInteger,CGFloat, and CFIndex—to provide a consistent means of representing values in 32- and 64-bit environments. In a 32-bit environment, NSInteger and NSUInteger are defined as int and unsigned int, respectively. In 64-bit environments, NSInteger and NSUInteger are defined as long and unsigned long, respectively. To avoid the need to use different printf-style type specifiers depending on the platform, you can use the specifiers shown in this link for both 32 bit and 64 bit environment.

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