A NSInteger
ma 32 bity na platformach 32-bitowych i 64 bity na platformach 64-bitowych. Czy istnieje NSLog
specyfikator, który zawsze odpowiada rozmiarowi NSInteger
?
Ustawiać
- Xcode 3.2.5
- Kompilator llvm 1.6 (to ważne; gcc tego nie robi)
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF
włączone
To przysparza mi trochę żalu:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
@autoreleasepool {
NSInteger i = 0;
NSLog(@"%d", i);
}
return 0;
}
W przypadku kodu 32-bitowego potrzebuję %d
specyfikatora. Ale jeśli używam %d
specyfikatora, pojawia się ostrzeżenie podczas kompilacji dla wersji 64-bitowej, sugerujące użycie %ld
zamiast tego.
Jeśli używam %ld
dopasowania rozmiaru 64-bitowego, podczas kompilacji dla kodu 32-bitowego pojawia się ostrzeżenie sugerujące użycie %d
zamiast tego.
Jak naprawić oba ostrzeżenia jednocześnie? Czy istnieje specyfikator, którego mogę użyć i który działa na którymkolwiek z nich?
Ma to również wpływ [NSString stringWithFormat:]
i [[NSString alloc] initWithFormat:]
.
źródło
static inline NSIntToLong(NSInteger i) {return (long)i;}
. Pozwala to uniknąć całkowitego wyłączenia sprawdzania typu (tj. Jeśli typ i się zmieni).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
Przyjęta odpowiedź jest absolutnie rozsądna, zgodna ze standardami i poprawna. Jedynym problemem jest to, że już nie działa, co jest całkowitą winą Apple'a.
Format% zd to standardowy format C / C ++ dla size_t i ssize_t. Podobnie jak NSInteger i NSUInteger, size_t i ssize_t są 32-bitowe w systemie 32-bitowym i 64-bitowym w systemie 64-bitowym. I dlatego drukowanie NSInteger i NSUInteger przy użyciu% zd działało.
Jednak NSInteger i NSUInteger są zdefiniowane jako „długie” w systemie 64-bitowym i jako „int” w systemie 32-bitowym (czyli 64-bitowym). Obecnie size_t jest zdefiniowany jako „long” we wszystkich systemach, który ma taki sam rozmiar jak NSInteger (64- lub 32-bitowy), ale jest innego typu. Albo ostrzeżenia Apple uległy zmianie (więc nie pozwala na przekazanie niewłaściwego typu do printf, mimo że ma odpowiednią liczbę bitów), albo podstawowe typy dla size_t i ssize_t uległy zmianie. Nie wiem który, ale% zd jakiś czas temu przestał działać. Obecnie nie ma formatu, który drukowałby NSInteger bez ostrzeżenia w systemach 32- i 64-bitowych.
Więc jedyne, co możesz niestety zrobić: Użyj% ld i rzutuj swoje wartości z NSInteger na long lub z NSUInteger na unsigned long.
Gdy nie będziesz już tworzyć wersji 32-bitowej, możesz po prostu użyć% ld bez rzutowania.
źródło
Elementy formatujące pochodzą ze standardowej funkcji printf systemu UNIX / POSIX. Użyj % lu dla unsigned long ,% ld dla long,% lld dla long i % llu dla unsigned long . Wypróbuj man printf na konsoli, ale na Macu jest niekompletny. Strony podręcznika systemu Linux są bardziej przejrzyste http://www.manpages.info/linux/sprintf.3.html
Oba ostrzeżenia można naprawić tylko przez NSLog (@ "% lu", (unsigned long) arg); połączone z rzutowaniem, ponieważ kod zostanie skompilowany w wersji 32 i 64-bitowej na iOS. W przeciwnym razie każda kompilacja tworzy osobne ostrzeżenie.
źródło