NSLog/printf specifier for NSInteger?

The accepted answer is absolutely reasonable, it is standard conforming, and correct. The only problem is that it doesn't work anymore, which is completely Apple's fault.

The format %zd is the C/C++ standard format for size_t and ssize_t. Like NSInteger and NSUInteger, size_t and ssize_t are 32 bit on a 32 bit system, and 64 bit on a 64 bit system. And that's why printing NSInteger and NSUInteger using %zd worked.

However, NSInteger and NSUInteger are defined as "long" on a 64 bit system, and as "int" on a 32 bit system (which is 64 vs 32 bit). Today, size_t is defined on "long" on all systems, which is the same size as NSInteger (either 64 or 32 bit), but a different type. Either Apple's warnings have changed (so it doesn't allow passing the wrong type to printf, even though it has the right number of bits), or the underlying types for size_t and ssize_t have changed. I don't know which one, but %zd stopped working some time ago. There is no format today that will print NSInteger without warning on both 32 and 64 bit systems.

So the only thing you can do unfortunately: Use %ld, and cast your values from NSInteger to long, or from NSUInteger to unsigned long.

Once you don't build for 32 bit anymore, you can just use %ld, without any cast.


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.