web-dev-qa-db-fra.com

Pourquoi une variable NSInteger doit-elle être convertie en long lorsqu'elle est utilisée comme argument de format?

NSInteger myInt = 1804809223;
NSLog(@"%i", myInt); <==== 

Le code ci-dessus génère une erreur:

Values of type "NSInteger" should not be used as format arguments: add an explicit cast to 'long' instead.

Le bon message NSLog est en fait NSLog(@"%lg", (long) myInt); Pourquoi dois-je convertir la valeur entière de myInt en long si je souhaite que la valeur soit affichée?

141
Daniel Lee

Vous obtenez cet avertissement si vous compilez sous OS X (64 bits), car sur cette plate-forme, NSInteger est défini en tant que long et correspond à un entier 64 bits. Le format %i, En revanche, est destiné à int, qui est 32 bits. Donc, le format et le paramètre réel ne correspondent pas en taille.

Puisque NSInteger est 32 bits ou 64 bits, selon la plate-forme, le compilateur recommande d'ajouter un transtypage à long en général.

Mise à jour: Étant donné qu'iOS 7 prend également en charge la version 64 bits, vous pouvez obtenir le même avertissement lors de la compilation pour iOS.

191
Martin R

Vous n'avez rien à rediffuser si vos spécificateurs de format correspondent à vos types de données. Voir la réponse de Martin R pour quels types natifs NSInteger est défini par.

Ainsi, sur OS X 64 bits, vous pouvez écrire vos instructions de journal de la manière suivante:

NSLog(@"%ld",  myInt); 

sur iOS, vous pouvez écrire:

NSLog(@"%d",  myInt); 

et tout fonctionnera sans plâtre.

De toute façon, une des raisons d'utiliser des transtypes, du moins dans le code sans interface utilisateur, est qu'un bon code a tendance à être porté sur toutes les plates-formes, et si vous transformez explicitement vos variables, il compilera proprement à la fois en 32 et 64 bits:

NSLog(@"%ld",  (long)myInt);

Cela aidera également votre code iOS lors du passage à la version 64 bits, si jamais il venait à iOS. Ou lorsque iOS et OS X sont fusionnés sur toute la ligne.

Et notez que cela ne vaut pas seulement pour les instructions NSLog, qui ne sont finalement que des aides au débogage, mais également pour [NSString stringWithFormat:] et amis, qui sont des éléments légitimes du code de production.

36
Monolo

Au lieu de transmettre un NSInteger à NSLog, transmettez simplement un NSNumber. Cela permettra de contourner tous les moulages et de choisir le bon spécificateur de format de chaîne.

NSNumber foo = @9000;
NSLog(@"foo: %@", foo);
NSInteger bar = 9001;
NSLog(@"bar: %@", @(bar));

Cela fonctionne également pour NSUIntegers sans avoir à vous soucier de cela. Voir la réponse à NSInteger et NSUInteger dans un environnement mixte 64 bits/32 bits

22
orkoden

Il garde l'avertissement lorsque vous utilisez NSLog(@"%ld", (long)myInt);, mais arrête l'avertissement après la déclaration de modification en long myInt = 1804809223; dans iOS 10.

0
Yao Li