Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

objective c implicit conversion loses integer precision 'NSUInteger'

Following a tutorial on treehouse, I'm see this popular Object-C warning message in XCode.

My button function

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

I see it on the NSUInteger line, I've few a few of the similar stackoverflows and they seem to talk about 32bit vs 64bit numbers and type casting, but not sure how to do that here?

My predictionArray

- (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.
}

enter image description here

like image 237
Leon Gaban Avatar asked Oct 15 '13 02:10

Leon Gaban


2 Answers

You can safely suppress the warning with a cast.

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

It's not always safe to suppress warnings, so don't go casting things to get rid of the warnings until you figure out whether the operation is safe.

What's going on here is that NSUInteger is, on your platform, a typedef for a 64-bit integer type. It's not always 64 bits, just on some platforms. The compiler is warning you that some of those bits are getting thrown away. If you know that these bits are unimportant, you can just use a cast.

In this case, the result is that index will always be under 232-1. If it's even remotely possible for predictionArray to contain 232 or more elements, then your program has an error and you'll have to construct a 64-bit version of arc4random_uniform(). You can ensure this with the following code:

assert(predictionArray.count <= (uint32_t) -1);
like image 142
Dietrich Epp Avatar answered Jan 03 '23 17:01

Dietrich Epp


As per my comment, arc4random_uniform() takes in, and returns, a u_int32_t, an unsigned integer that is always 32 bits, regardless of target architecture. However, predictionArray.count returns an NSUInteger, which is typedefd differently for 32-bit and 64-bit systems; it's 32 bits (unsigned int) on a 32-bit system, and 64-bits (unsigned long) on a 64-bit system. If you're running on a 64-bit system, passing in a 64-bit NSUInteger to a function expecting a 32-bit integer will cause the compiler to complain that you're throwing away bits.

like image 23
Itai Ferber Avatar answered Jan 03 '23 18:01

Itai Ferber