NSLog/printf specifier for NSInteger?

Steven Fisher picture Steven Fisher · Dec 10, 2010 · Viewed 75.3k times · Source

A NSInteger is 32 bits on 32-bit platforms, and 64 bits on 64-bit platforms. Is there a NSLog specifier that always matches the size of NSInteger?

Setup

  • Xcode 3.2.5
  • llvm 1.6 compiler (this is important; gcc doesn't do this)
  • GCC_WARN_TYPECHECK_CALLS_TO_PRINTF turned on

That's causing me some grief here:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    @autoreleasepool {
        NSInteger i = 0;
        NSLog(@"%d", i);
    }
    return 0;
}

For 32 bit code, I need the %d specifier. But if I use the %d specifier, I get a warning when compiling for 64 bit suggesting I use %ld instead.

If I use %ld to match the 64 bit size, when compiling for 32 bit code I get a warning suggesting I use %d instead.

How do I fix both warnings at once? Is there a specifier I can use that works on either?

This also impacts [NSString stringWithFormat:] and [[NSString alloc] initWithFormat:].

Answer

Lily Ballard picture Lily Ballard · Dec 10, 2010

Updated answer:

You can make use of the z and t modifiers to handle NSInteger and NSUInteger without warnings, on all architectures.

You want to use %zd for signed, %tu for unsigned, and %tx for hex.

This information comes courtesy of Greg Parker.


Original answer:

The official recommended approach is to use %ld as your specifier, and to cast the actual argument to a long.