【问题标题】:objective c implicit conversion loses integer precision 'NSUInteger'目标c隐式转换丢失整数精度'NSUInteger'
【发布时间】:2013-10-22 17:33:19
【问题描述】:

按照关于树屋的教程,我在 XCode 中看到了这个流行的 Object-C 警告消息。

我的按钮功能

- (IBAction)buttonPressed:(UIButton *)sender {
    NSUInteger index = arc4random_uniform(predictionArray.count);
    self.predictionLabel.text = [predictionArray objectAtIndex:index];
}

我在 NSUInteger 行上看到它,我有几个类似的 stackoverflow,他们似乎在谈论 32 位与 64 位数字和类型转换,但不知道如何在这里做到这一点?

我的预测数组

- (void)viewDidLoad
{
    [super viewDidLoad];
    predictionArray = [[NSArray alloc] initWithObjects:
                   @"It is certain", @"It is decidely so", @"All signs say YES", @"The stars are not aligned",
                   @"My reply is no",
                   @"It is doubtful",
                   @"Better not tell you now",
                   @"Concentrate and ask again",
                   @"Unable to answer now", nil];
// Do any additional setup after loading the view, typically from a nib.
}

【问题讨论】:

    标签: ios objective-c compiler-errors warnings


    【解决方案1】:

    您可以通过强制转换安全地抑制警告。

    NSUInteger index = arc4random_uniform((uint32_t) predictionArray.count);
    

    抑制警告并不总是安全,所以在确定操作是否安全之前,不要进行强制转换以消除警告。

    这里发生的情况是,NSUInteger 在您的平台上是 64 位整数类型的 typedef。它不是总是 64 位,只是在某些平台上。编译器警告您其中一些位正在被丢弃。如果您知道这些位不重要,则可以使用强制转换。

    在这种情况下,结果是index 将始终低于 232-1。如果predictionArray 甚至有可能包含 232 或更多元素,那么您的程序有错误,您必须构建一个 64 位版本的 arc4random_uniform()。您可以使用以下代码确保这一点:

    assert(predictionArray.count <= (uint32_t) -1);
    

    【讨论】:

    • 嗯,我刚试过这个,但仍然是同样的警告。那么我将 NSUInteger 投射为什么呢? (NSUInteger) 是什么意思。或者更重要的是,它警告我什么?
    • 谢谢!仍然试图理解这一点,所以NSUInteger 始终是 32 位整数?我尝试将其转换为 64 位并得到相同的错误。那一点点东西对我来说是新的,以前从来没有遇到过
    • Deitrich,我不想编辑你的答案并踩到脚趾,但我可能会扩展它来解释为什么演员表是必要的。 @LeonGaban arc4random_uniform() 接收并返回 uint32_t,这是一个始终为 32 位的无符号整数,与目标架构无关。但是,predictionArray.count 返回一个NSUInteger,对于 32 位和 64 位系统,typedefd 是不同的;在 32 位系统上是 32 位,在 64 位系统上是 64 位。如果您在 64 位系统上运行,则传入 64 位 NSUInteger 会导致编译器抱怨您正在丢弃位。
    • @ItaiFerber:在 Stack Overflow 上,没有什么比响应您的请求更让我烦恼的了……您显然知道答案。您可以 (1) 将您的知识放在评论中,(2) 将其编辑到我的答案中,(3) 创建您自己的答案。以后不要选择选项(4),请其他人代表您解释您所知道的事情。我不是你的秘书。
    • 那不是我的本意。您已经获得了赞成票,并且 Leon 将您的答案标记为正确 - 只需留下评论 (1) 就会将您的答案作为规范答案,即使它不完整并且我的评论是有效的。 (2) 有些人的答案被强行修改是极其冒犯的,我无意冒犯任何人。 (3) 如果你的答案已经被标记为正确,根据经验,即使我提出了一个更完整的答案,提问者也可能会忽略它。 (4) 所以我选择礼貌地推荐你扩展你的答案。就是这样。
    【解决方案2】:

    根据我的评论,arc4random_uniform() 接受并返回 u_int32_t,这是一个始终为 32 位的无符号整数,与目标架构无关。但是,predictionArray.count 返回一个NSUInteger,对于 32 位和 64 位系统,typedefd 是不同的;在 32 位系统上是 32 位 (unsigned int),在 64 位系统上是 64 位 (unsigned long)。如果您在 64 位系统上运行,将 64 位 NSUInteger 传递给需要 32 位整数的函数会导致编译器抱怨您正在丢弃位。

    【讨论】:

    • 感谢您的解释,所以如果我将 32 位数字发送到 64 位函数/方法中会减慢程序速度吗?或者只是说我可以更有效率。 arc4random_uniform() 有 64 位版本吗?还是我应该经常使用u_int32_t
    • @LeonGaban 一个不起眼的数量,如果有的话。您的 32 位数字必须扩展为 64 位;如果它是无符号的,那么它将自动扩展为 0,如果它是有符号且为负数,它将自动扩展为 1。这不是一个真正的问题。但是,如果您尝试将 64 位数字传递给 32 位函数,则部分数字可能会被丢弃(该函数仅获取低 32 位),并且编译器会抱怨(这就是为什么您必须确保你知道你在用演员做什么)。
    • @LeonGaban 不幸的是,没有 64 位版本的 arc4random* 函数,但继续使用它们,你会没事的。我建议不要在任何地方使用u_int32_t,因为根据定义,它是 32 位的。 NSUInteger 的优势是被苹果typedefd 为你匹配目标平台,所以你可以随时使用它并且知道你正在高效地做事(你不想随意限制你的大小数据,除非有意义且必要)。
    猜你喜欢
    • 2013-05-30
    • 1970-01-01
    • 2013-06-05
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 2017-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多