NSInteger myInt = 1804809223;
NSLog(@"%i", myInt); <====
Powyższy kod powoduje błąd:
Wartości typu „NSInteger” nie powinny być używane jako argumenty formatu; zamiast tego dodaj wyraźne rzutowanie do „długiego”
Poprawiony NSLog
komunikat to faktycznie NSLog(@"%lg", (long) myInt);
. Dlaczego muszę konwertować wartość całkowitą myInt
na, long
jeśli chcę, aby wartość była wyświetlana?
objective-c
xcode
casting
nsinteger
Daniel Lee
źródło
źródło
NSLog(@"%ld", (long) myInt);
,long
obsada ma dopasować ją dol
kwalifikatora%ld
, ale wszystko to jest niepotrzebne, ponieważNSLog(@"%d", myInt);
jest wystarczające (biorąc pod uwagę, że widzimy, żemyInt
nie jestlong
. Podsumowując, rzucasz,myInt
jeśli używasz długiego kwalifikatora w formacie string, ale nie ma potrzeby używania w tym miejscu kwalifikatora formatu długich łańcuchów anilong
rzutowaniaNSInteger
jest długi), ale brzmi to tak, jakbyś kompilował z celem OS X (gdzie jest ).NSInteger
long
Odpowiedzi:
To ostrzeżenie jest wyświetlane, jeśli kompilujesz w systemie OS X (64-bitowym), ponieważ na tej platformie
NSInteger
jest zdefiniowana jakolong
i jest 64-bitową liczbą całkowitą. Z%i
drugiej strony format jest przeznaczony dlaint
32-bitowych. Zatem format i rzeczywisty parametr nie pasują do rozmiaru.Ponieważ
NSInteger
jest 32-bitowy lub 64-bitowy, w zależności od platformy, kompilator zaleca dodanie rzutowania dolong
ogólnie .Aktualizacja: ponieważ iOS 7 obsługuje teraz również wersję 64-bitową, możesz otrzymać to samo ostrzeżenie podczas kompilacji dla iOS.
źródło
NSLog(@"%ld", (long) myInt)
, działa poprawnie na 32-bitowym i 64-bitowym.long myInt = [myNumber longValue];
. Jednak wiele metod (Core) Foundation używa NS (U) Integer jako parametru lub wartości zwracanej, więc ogólny problem pozostaje. W Twojej aplikacji może mieć również sens użycie NS (U) Integer, aby uzyskać większy dostępny zakres na urządzeniach 64-bitowych.Nie musisz rzucać do niczego, jeśli specyfikatory formatu pasują do twoich typów danych. Zobacz odpowiedź Martina R., aby dowiedzieć się, jak to zrobić
NSInteger
definicji w kategoriach typów natywnych.Tak więc w przypadku kodu przeznaczonego do tworzenia dla środowisk 64-bitowych możesz pisać instrukcje dziennika w następujący sposób:
podczas gdy dla środowisk 32-bitowych możesz napisać:
i będzie działać bez odlewów.
Jednym z powodów, dla których warto mimo wszystko używać rzutowań, jest to, że dobry kod jest zwykle przenoszony między platformami, a jeśli rzutujesz zmienne jawnie, skompiluje się on czysto zarówno na 32, jak i 64 bitach:
Zauważ, że dotyczy to nie tylko instrukcji NSLog, które w końcu są tylko pomocami w debugowaniu, ale także
[NSString stringWithFormat:]
różnych komunikatów pochodnych, które są uprawnionymi elementami kodu produkcyjnego.źródło
Zamiast przekazywać NSInteger do NSLog, wystarczy przekazać NSNumber. Spowoduje to obejście wszystkich rzutów i wybranie odpowiedniego specyfikatora formatu ciągu.
Działa również w przypadku NSUIntegers, nie martwiąc się o to. Zobacz odpowiedź na NSInteger i NSUInteger w mieszanym środowisku 64-bitowym / 32-bitowym
źródło
Zachowuje ostrzeżenie podczas używania
NSLog(@"%ld", (long)myInt);
, ale przestaje ostrzegać po deklaracji zmiany nalong myInt = 1804809223;
w iOS 10.źródło
OS X używa kilku typów danych - NSInteger, NSUInteger, CGFloat i CFIndex - aby zapewnić spójne sposoby przedstawiania wartości w środowiskach 32- i 64-bitowych. W środowisku 32-bitowym NSInteger i NSUInteger są zdefiniowane odpowiednio jako int i unsigned int. W środowiskach 64-bitowych NSInteger i NSUInteger są definiowane odpowiednio jako long i unsigned long. Aby uniknąć konieczności używania różnych specyfikatorów typu printf w zależności od platformy, można użyć specyfikatorów pokazanych w tym łączu zarówno dla środowiska 32-bitowego, jak i 64-bitowego.
źródło