Alternatives to type casting when formatting NS(U)Integer on 32 and 64 bit architectures?

From http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html:

  • z
    Specifies that a following […] conversion specifier applies to a size_t or the corresponding signed integer type argument;
  • t
    Specifies that a following […] conversion specifier applies to a ptrdiff_t or the corresponding unsigned type argument;

And from http://en.wikipedia.org/wiki/Size_t#Size_and_pointer_difference_types:

  • size_t is used to represent the size of any object (including arrays) in the particular implementation. It is used as the return type of the sizeof operator.
  • ptrdiff_t is used to represent the difference between pointers.

On the current OS X and iOS platforms we have

typedef __SIZE_TYPE__ size_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;

where __SIZE_TYPE__ and __PTRDIFF_TYPE__ are predefined by the
compiler. For 32-bit the compiler defines

#define __SIZE_TYPE__ long unsigned int
#define __PTRDIFF_TYPE__ int

and for 64-bit the compiler defines

#define __SIZE_TYPE__ long unsigned int
#define __PTRDIFF_TYPE__ long int

(This may have changed between Xcode versions. Motivated by @user102008’s
comment, I have checked this with Xcode 6.2 and updated the answer.)

So ptrdiff_t and NSInteger are both typedef’d to the same type:
int on 32-bit and long on 64-bit. Therefore

NSLog(@"%td", i);
NSLog(@"%tu", u);

work correctly and compile without warnings on all current
iOS and OS X platforms.

size_t and NSUInteger have the same size on all platforms, but
they are not the same type, so

NSLog(@"%zu", u);

actually gives a warning when compiling for 32-bit.

But this relation is not fixed in any standard (as far as I know), therefore I would
not consider it safe (in the same sense as assuming that long has the same size
as a pointer is not considered safe). It might break in the future.

The only alternative to type casting that I know of is from the answer to “Foundation types when compiling for arm64 and 32-bit architecture”, using preprocessor macros:

// In your prefix header or something
#if __LP64__
#define NSI "ld"
#define NSU "lu"
#else
#define NSI "d"
#define NSU "u"
#endif

NSLog(@"i=%"NSI, i);
NSLog(@"u=%"NSU, u);

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)