A NSInteger
ist 32 Bit auf 32-Bit-Plattformen und 64 Bit auf 64-Bit-Plattformen. Gibt es einen NSLog
Bezeichner, der immer der Größe von entspricht NSInteger
?
Konfiguration
- Xcode 3.2.5
- llvm 1.6 Compiler (das ist wichtig; gcc macht das nicht)
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF
eingeschaltet
Das macht mir hier Sorgen:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
@autoreleasepool {
NSInteger i = 0;
NSLog(@"%d", i);
}
return 0;
}
Für 32-Bit-Code benötige ich den %d
Bezeichner. Wenn ich jedoch den %d
Bezeichner verwende, wird beim Kompilieren für 64-Bit eine Warnung angezeigt, die darauf hinweist, dass ich %ld
stattdessen verwende.
Wenn ich %ld
die 64-Bit-Größe anpasse, wird beim Kompilieren für 32-Bit-Code eine Warnung angezeigt, die darauf hinweist, dass ich %d
stattdessen verwende.
Wie behebe ich beide Warnungen gleichzeitig? Gibt es einen Bezeichner, mit dem ich arbeiten kann?
Dies wirkt sich auch auf [NSString stringWithFormat:]
und aus [[NSString alloc] initWithFormat:]
.
quelle
static inline NSIntToLong(NSInteger i) {return (long)i;}
. Dadurch wird vermieden, dass die Typprüfung vollständig deaktiviert wird (dh wenn sich der Typ von i ändert).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
Die akzeptierte Antwort ist absolut vernünftig, standardkonform und korrekt. Das einzige Problem ist, dass es nicht mehr funktioniert, was völlig Apples Schuld ist.
Das Format% zd ist das C / C ++ - Standardformat für size_t und ssize_t. Wie NSInteger und NSUInteger sind size_t und ssize_t auf einem 32-Bit-System 32-Bit und auf einem 64-Bit-System 64-Bit. Und deshalb hat das Drucken von NSInteger und NSUInteger mit% zd funktioniert.
NSInteger und NSUInteger sind jedoch auf einem 64-Bit-System als "long" und auf einem 32-Bit-System als "int" definiert (64 gegenüber 32 Bit). Heute wird size_t definiert auf „lang“ auf allen Systemen, das ist die gleiche Größe wie NSInteger (entweder 64 oder 32 Bit), sondern ein anderer Typ. Entweder haben sich die Warnungen von Apple geändert (sodass der falsche Typ nicht an printf übergeben werden kann, obwohl die richtige Anzahl von Bits vorhanden ist), oder die zugrunde liegenden Typen für size_t und ssize_t haben sich geändert. Ich weiß nicht welche, aber% zd hat vor einiger Zeit aufgehört zu arbeiten. Es gibt heute kein Format, das NSInteger ohne Warnung auf 32- und 64-Bit-Systemen druckt.
Das Einzige, was Sie leider tun können: Verwenden Sie% ld und wandeln Sie Ihre Werte von NSInteger in long oder von NSUInteger in unsigned long um.
Sobald Sie nicht mehr für 32 Bit bauen, können Sie einfach% ld ohne Cast verwenden.
quelle
Die Formatierer stammen aus der Standardfunktion UNIX / POSIX printf. Verwenden Sie % lu für unsigned long ,% ld für long,% lld für long long und % llu für unsigned long long . Versuchen Sie es mit man printf auf der Konsole, aber auf dem Mac ist es unvollständig. Die Linux-Manpages sind expliziter http://www.manpages.info/linux/sprintf.3.html
Beide Warnungen können nur von NSLog behoben werden (@ "% lu", (unsigned long) arg); kombiniert mit einer Besetzung, da der Code in 32 UND 64 Bit für iOS kompiliert wird. Andernfalls erstellt jede Zusammenstellung eine separate Warnung.
quelle