Objective-C隐式转换将整数精度'NSUInteger'(aka'unsigned long')转换为'int'警告


187

我正在做一些练习,并收到警告,指出:

隐式转换将失去整数精度:将'NSUInteger'(aka'unsigned long')转换为'int'

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
    @autoreleasepool {

        NSArray *myColors;

        int i;
        int count;

        myColors = @[@"Red", @"Green", @"Blue", @"Yellow"];

        count = myColors.count; //  <<< issue warning here

        for (i = 0; i < count; i++)

        NSLog (@"Element %i = %@", i, [myColors objectAtIndex: i]);
    }

    return 0;
}

屏幕截图

Answers:


470

所述count的方法NSArray返回的NSUInteger,并且64位OS X平台上

  • NSUInteger被定义为unsigned long,并且
  • unsigned long 是一个64位无符号整数。
  • int 是一个32位整数。

因此int,“”的数据类型比的小NSUInteger,因此是编译器警告。

另请参见“基础数据类型参考”中的NSUInteger

在构建32位应用程序时,NSUInteger是32位无符号整数。64位应用程序将NSUInteger视为64位无符号整数。

要解决该编译器警告,您可以将局部count变量声明为

NSUInteger count;

或(如果您确定您的数组绝不会包含多个2^31-1元素!),请添加一个显式的强制类型转换:

int count = (int)[myColors count];

19
补充一下-我在Xcode 5项目中突然收到大量警告和错误,我对这个答案投了赞成票。您提到了64位,这使我了解了我的构建设置。Xcode将其更改为64位模式,这引发了错误。将其更改回arvm7修复了所有问题。
罗伯特·克莱格

1
@Tander在编译64位与armv7之间有性能差异吗?
Shaun Budhram 2014年

1
@ShaunBudhram通过它的外观不。我没看到任何区别。这只会在大量使用CPU的应用程序中有所作为-例如,游戏会受益于64位编译。
罗伯特·克莱格

7
“从2015年2月1日开始,上载到App Store的新iOS应用程序必须包含64位支持 ...”- 苹果开发人员新闻和更新,2014

2
@JayprakashDubey:Apple无法看到您的编译器警告,因为您将二进制编译的应用程序提交到App Store。因此,由于编译器警告,您的应用无法被拒绝。当然,您应该修复它们以使您的应用正常运行。
马丁R

24

与Martin的回答相反,即使知道数组的元素数不超过2 ^ 31-1,强制转换为int(或忽略警告)也不总是安全的。为64位编译时不行。

例如:

NSArray *array = @[@"a", @"b", @"c"];

int i = (int) [array indexOfObject:@"d"];
// indexOfObject returned NSNotFound, which is NSIntegerMax, which is LONG_MAX in 64 bit.
// We cast this to int and got -1.
// But -1 != NSNotFound. Trouble ahead!

if (i == NSNotFound) {
    // thought we'd get here, but we don't
    NSLog(@"it's not here");
}
else {
    // this is what actually happens
    NSLog(@"it's here: %d", i);

    // **** crash horribly ****
    NSLog(@"the object is %@", array[i]);
}

6
正确的说法是indexOfObject:将结果转换为一个坏主意。我的回答是针对问题中的特定代码,并且该count方法无法返回NSNotFound。我不建议一般强制转换为int或忽略警告。抱歉,如果不清楚。实际上,if (i == NSNotFound)如果将示例代码编译为64位,则示例代码将在生成警告,因此不会引起人们的注意。
Martin R

@Adrian:如果您不介意,您建议询问者做什么?
moonman239

@ moonman239通常,我会尽可能使用正确类型的变量(@MartinR的第一个建议),而不是强制转换(第二个建议)。正如他指出的那样,在这种情况下强制转换是安全的,但是我认为这是一种不良习惯,因为它可能会带来意想不到的后果(例如在我的示例中)。我发帖是因为我被这种特定情况所困扰(尽管这对==编译器警告是个好主意,我一定错过了)。
阿德里安

2
我认为count将比indexOfObject更加频繁地使用,并且使用NSInteger膨胀for循环只是为了不具有“可怜的”编码风格是胡说八道。您应该只注意indexOfObject,并确保在那里使用NSIntegers,所有简单地将某物计数为整数的东西都可以作为int使用,尤其是在以方法为重点的情况下
NikkyD

5

在项目>构建设置更改键“ 类型检测,调用的printf / scanf函数NO

说明: [如何运作]

检查对printf和scanf等的调用,以确保提供的参数具有与指定的格式字符串相对应的类型,并且确保在格式字符串中指定的转换有意义。

希望它能工作

其他警告

目标C隐式转换将整数精度'NSUInteger'(aka'unsigned long')转换为'int

将密钥“ 隐式转换为32Bits类型>调试> * 64体系结构:否

[ 注意:可能会使64位架构转换的其他警告无效]


如果您只想将32位库转换为64位,这是一个很有前途的选择。
2015年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.