18 votes

NSInteger et NSUInteger dans un environnement mixte 64 bits / 32 bits

J'ai un certain nombre de spécificateurs de format de chaîne dans les appels de NSLog / NSAssert etc. qui utilisent %d et %u avec les types NSInteger (= int sur 32 bits) et NSUInteger (= unsigned int sur 32 bits) respectivement.

Lors de la conversion de l'application en 64 bits, cela génère des avertissements (bien sûr), car %ld %lu est attendu pour ce qui est maintenant un type long et unsigned long.

Convertir simplement les spécificateurs de format introduira bien sûr les avertissements inverses dans la version 32 bits.
Donc la seule solution que je vois pour devenir sans avertissement est d'utiliser les spécificateurs 64 bits, et de caster vers les types de valeur 64 bits partout où un avertissement est donné dans la version 32 bits.

Mais je me demandais s'il existe peut-être des spécificateurs de format spécifiquement pour le type NSInteger et NSUInteger qui fonctionneraient sur les deux architectures sans cast?

39voto

ilya n. Points 6610

Je pense que la manière la plus sûre est de les encapsuler dans des instances de NSNumber.

NSLog(@"Le nombre est %@", @(number)); // utilise le plus haut niveau d'abstraction

Cette encapsulation n'a généralement pas besoin de créer un nouvel objet grâce à la magie des pointeurs étiquetés.

Si vous ne voulez vraiment pas utiliser NSNumber, vous pouvez caster les types primitifs manuellement, comme d'autres l'ont suggéré :

NSLog(@"Le nombre est %ld", (long)number); // fonctionne de la même manière sur 32 bits et 64 bits

17voto

d0m1n1k Points 338

Vous pouvez également utiliser %zd (NSInteger) et %tu (NSUInteger) lors de l'enregistrement dans la console.

NSInteger integer = 1;
NSLog(@"premier nombre: %zd", integer);

NSUInteger uinteger = 1;
NSLog(@"deuxième nombre: %tu", uinteger);

Également disponible ici.

1voto

Martin R Points 105727

Non, malheureusement, il n'existe pas de format printf qui correspond directement à NS(U)Integer. Donc, pour un code indépendant de l'architecture, vous devez convertir tout en la variante "long" (comme le suggère le "Fix-it" Xcode) :

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

La seule alternative que je connaisse provient de Types de fondation lors de la compilation pour arm64 et une architecture 32 bits :

// Dans le fichier d'en-tête précompilé :
#if __LP64__
#define NSI "ld"
#define NSU "lu"
#else
#define NSI "d"
#define NSU "u"
#endif

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

en utilisant des macros de préprocesseur (mais même l'auteur de cette réponse l'appelle une "approche franchement horrible").

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X