Objective c 当用作格式参数时,为什么NSInteger变量必须强制转换为long? NSInteger myInt=1804809223; NSLog(@“%i”,myInt)

Objective c 当用作格式参数时,为什么NSInteger变量必须强制转换为long? NSInteger myInt=1804809223; NSLog(@“%i”,myInt),objective-c,xcode,casting,nsinteger,Objective C,Xcode,Casting,Nsinteger,如果在OS X(64位)上编译,则会收到此警告,因为在该平台上,NSInteger定义为long,是64位整数。另一方面,%i格式用于32位的int。因此,格式和实际参数的大小不匹配 由于NSInteger是32位或64位,具体取决于平台,编译器建议 向long添加强制转换的一般步骤 更新:由于iOS 7现在也支持64位,因此在编译时可以得到相同的警告 对于iOS。如果格式说明符与数据类型匹配,则无需强制转换任何内容。有关如何根据本机类型定义NSInteger的详细信息,请参见Martin R的

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

由于
NSInteger
是32位或64位,具体取决于平台,编译器建议 向
long
添加强制转换的一般步骤

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

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

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

NSInteger myInt = 1804809223;
NSLog(@"%i", myInt); <==== 
而对于32位环境,您可以编写:

NSLog(@"%ld",  myInt); 
没有石膏,一切都能正常工作

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

NSLog(@"%d",  myInt); 

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

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

NSLog(@"%ld",  (long)myInt);
它也适用于整数,而不必担心这一点。
请参见对

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

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

@danielle,如果您使用
NSLog(@“%ld”,(long)myInt)
,长
强制转换是为了使其与
%ld
l
限定符匹配,但所有这些都是不必要的,因为
NSLog(@“%d”,myInt)
就足够了(因为我们可以看到
myInt
不是
long
。底线是,如果在格式字符串中使用长限定符,您可以强制转换
myInt
,但不需要在此处使用长字符串格式限定符或
long
强制转换。显然,NSLog(@“%i”,myInt)不是真的;就足够了,因为您将收到我上面显示的错误消息。@Danielle看到Martin R的评论。您用iOS标记发布了您的问题(其中
NSInteger
不长),但听起来像是用OS X目标编译的(其中
NSInteger
很长
).Ahh,我明白了。我不知道iOS和OSX会使NSInteger在位和类型上有所不同。我在iOS 7上遇到了这个错误。因为只有最新的iPhone 5S是64位的,如果我将其设置为最长,它会在较旧的32位设备上引起任何问题吗?@BartSimpson:显式大小写为“long”,如
NSLog(@“%ld”,(long)myInt)
,它可以正确地在32位和64位上工作。@MartinR如果我们正在铸造,为什么不首先使用long?@fulldestrible:当然可以在这里使用long:
long myInt=[myNumber longValue];
。但是许多(核心)基础方法使用NS(U)整数作为参数或返回值,因此一般问题仍然存在。在应用程序中使用NS(U)也是有意义的整数,以便在64位设备上获得更大的可用范围。因此,既然需要这种黑客攻击,那么首先使用NSInteger是否仍然是最佳做法?@FULLDELENDE这只是运行时解释的代码中的一个问题,例如格式字符串。Al编译代码利用NSInteger typedef。使用NSInteger是最佳做法,beca使用定义它的方式有很好的理由。我认为所选答案在技术上是问题的最佳答案,但如果您想知道如何避免每次出现并防止警告,那么我发现这是最好的解决方案。
NSNumber foo = @9000;
NSLog(@"foo: %@", foo);
NSInteger bar = 9001;
NSLog(@"bar: %@", @(bar));