NSInteger y NSUInteger en un entorno mixto de 64 bits / 32 bits


Tengo una buena cantidad de especificadores de formato de cadena en NSLog / NSAssert, etc. llamadas que usan %d y %u con los tipos NSInteger (= int on 32bit) y NSUInteger (= unsigned int on 32bit) respectivamente.

Al convertir la aplicación a 64 bits, esto da advertencias (por supuesto), ya que %ld %lu se espera para lo que ahora se convirtió en un tipo long y unsigned long.

Simplemente convertir los especificadores de formato, por supuesto, introducirá las advertencias inversas en la compilación de 32 bits.
Así que la única solución que veo para convertirse en warning free es usar el 64bit especificadores, y fundición a los tipos de valor de 64 bits en todas partes se da una advertencia en la compilación de 32 bits.

Pero me preguntaba si tal vez hay especificadores de formato específicamente para el tipo NSInteger y NSUInteger que funcionarían en ambas arquitecturas sin fundición?

Author: Pieter, 2013-12-03

3 answers

Creo que la forma más segura es encajonarlos en NSNumber instancias.

NSLog(@"Number is %@", @(number)); // use the highest level of abstraction

Este boxeo no suele tener que crear un nuevo objeto gracias a tagged pointer magic.

Si realmente no desea usar NSNumber, puede convertir tipos primitivos manualmente, como otros sugirieron:

NSLog(@"Number is %ld", (long)number); // works the same on 32-bit and 64-bit
 59
Author: ilya n.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-03 21:49:14

También puede utilizar %zd (NSInteger) y %tu (NSUInteger) al iniciar sesión en la consola.

NSInteger integer = 1;
NSLog(@"first number: %zd", integer);

NSUInteger uinteger = 1;
NSLog(@"second number: %tu", uinteger);

También se puede encontrar aquí.

 37
Author: d0m1n1k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:38

No , (desafortunadamente) no hay ningún formato printf que corresponda directamente a NS(U)Integer. Así que para el código independiente de la arquitectura, tienes que convertir todo al " largo" variante (como sugiere el Xcode "Fix-it"):

NSInteger i = ...;
NSLog(@"%ld", (long)i);

La única alternativa que conozco es de Tipos Foundation al compilar para arm64 y arquitectura de 32 bits :

// In the precompiled header file:
#if __LP64__
#define NSI "ld"
#define NSU "lu"
#else
#define NSI "d"
#define NSU "u"
#endif

NSInteger i = ...;
NSLog(@"i=%"NSI, i);

Usando macros de preprocesador (pero incluso el autor de esa respuesta lo llama un "admittedly awful approach").

 4
Author: Martin R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:26