A NSInteger
est 32 bits sur les plates-formes 32 bits et 64 bits sur les plates-formes 64 bits. Existe-t-il un NSLog
spécificateur qui correspond toujours à la taille de NSInteger
?
Installer
- Xcode 3.2.5
- compilateur llvm 1.6 (c'est important; gcc ne le fait pas)
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF
allumé
Cela me cause du chagrin ici:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
@autoreleasepool {
NSInteger i = 0;
NSLog(@"%d", i);
}
return 0;
}
Pour le code 32 bits, j'ai besoin du %d
spécificateur. Mais si j'utilise le %d
spécificateur, j'obtiens un avertissement lors de la compilation pour 64 bits suggérant que j'utilise à la %ld
place.
Si j'utilise %ld
pour correspondre à la taille 64 bits, lors de la compilation pour le code 32 bits, je reçois un avertissement suggérant que j'utilise à la %d
place.
Comment corriger les deux avertissements à la fois? Y a-t-il un spécificateur que je peux utiliser qui fonctionne sur l'un ou l'autre?
Cela a également un impact sur [NSString stringWithFormat:]
et [[NSString alloc] initWithFormat:]
.
la source
static inline NSIntToLong(NSInteger i) {return (long)i;}
. Cela évite de désactiver complètement la vérification de type (c'est-à-dire si le type de i change).static inline long NSIntToLong(NSInteger i) {return (long)i;}
NSLog(@"%@",@(mynsint));
stackoverflow.com/questions/20355439/…%zd
:Values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead
La réponse acceptée est tout à fait raisonnable, conforme à la norme et correcte. Le seul problème est que cela ne fonctionne plus, ce qui est entièrement la faute d'Apple.
Le format% zd est le format standard C / C ++ pour size_t et ssize_t. Comme NSInteger et NSUInteger, size_t et ssize_t sont 32 bits sur un système 32 bits et 64 bits sur un système 64 bits. Et c'est pourquoi l'impression de NSInteger et NSUInteger à l'aide de% zd a fonctionné.
Cependant, NSInteger et NSUInteger sont définis comme "long" sur un système 64 bits et comme "int" sur un système 32 bits (qui est 64 contre 32 bits). Aujourd'hui, size_t est défini sur "long" sur tous les systèmes, ce qui est de la même taille que NSInteger (64 ou 32 bits), mais d'un type différent. Soit les avertissements d'Apple ont changé (il ne permet donc pas de passer le mauvais type à printf, même s'il a le bon nombre de bits), soit les types sous-jacents pour size_t et ssize_t ont changé. Je ne sais pas lequel, mais% zd a cessé de fonctionner il y a quelque temps. Il n'existe aujourd'hui aucun format permettant d'imprimer NSInteger sans avertissement sur les systèmes 32 et 64 bits.
Donc, la seule chose que vous pouvez faire malheureusement: utilisez% ld et transtypez vos valeurs de NSInteger en long, ou de NSUInteger en unsigned long.
Une fois que vous ne construisez plus pour 32 bits, vous pouvez simplement utiliser% ld, sans aucune distribution.
la source
Les formateurs proviennent de la fonction printf standard UNIX / POSIX. Utilisez % lu pour unsigned long ,% ld pour long,% lld pour long long et % llu pour unsigned long long . Essayez man printf sur la console, mais sur Mac, il est incomplet. Les pages de manuel Linux sont plus explicites http://www.manpages.info/linux/sprintf.3.html
Les deux avertissements ne peuvent être corrigés que par NSLog (@ "% lu", (unsigned long) arg); combiné avec un cast car le code sera compilé en 32 ET 64 bits pour iOS. Sinon, chaque compilation crée un avertissement distinct.
la source