Why does an NSInteger variable have to be cast to long when used as a format argument?
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 corrected 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?
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.
Since NSInteger
is 32-bit or 64-bit, depending on the platform, the compiler recommends
to add a cast to long
generally.
Update: Since iOS 7 supports 64-bit now as well, you can get the same warning when compiling for iOS.
You don't have to cast to anything if your format specifiers match your data types. See Martin R's answer for details on how NSInteger
is defined in terms of native types.
So for code intended to be built for 64-bit environments, you can write your log statements like this:
NSLog(@"%ld", myInt);
while for 32-bit environments you can write:
NSLog(@"%d", myInt);
and it will all work without casts.
One reason to use casts anyway 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:
NSLog(@"%ld", (long)myInt);
And notice this is true not just for NSLog statements, which are just debugging aids after all, but also for [NSString stringWithFormat:]
and the various derived messages, which are legitimate elements of production code.
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.
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