Alternativen zu type-casting, wenn die Formatierung NS(U)Integer auf 32-und 64-bit-Architekturen?
Mit der 64 bit version von iOS, wir können nicht %d
und %u
mehr format NSInteger
und NSUInteger
. Denn für 64 bit-die sind typedef würde long
und unsigned long
statt int
und unsigned int
.
Also Xcode wirft Warnungen, wenn Sie versuchen, format NSInteger mit %d.... Xcode ist nett zu uns und bietet einen Ersatz für diesen zwei Fällen, die aus einem l-Präfix-format-Bezeichner und eine Typumwandlung zu lange. Dann ist unser code sieht im Grunde so:
NSLog(@"%ld", (long)i);
NSLog(@"%lu", (unsigned long)u);
Welche, wenn Sie mich Fragen, ist ein Schmerz im Auge.
Vor ein paar Tagen jemand bei Twitter erwähnte der Formatbezeichner %zd
format signed-Variablen und - %tu
format unsigned Variablen auf 32-und 64-bit-Plattformen.
NSLog(@"%zd", i);
NSLog(@"%tu", u);
Scheint zu funktionieren. Und die mag ich mehr als typecasting.
Aber ich habe ehrlich gesagt keine Ahnung, warum diese Arbeit. Jetzt beide sind im Grunde Magische Werte für mich.
Ich habe ein wenig Forschung und fand heraus, dass die z
Präfix bedeutet, dass die folgenden Formatbezeichner hat die gleiche Größe wie size_t
. Aber ich habe absolut keine Ahnung, was das Präfix t
bedeutet. Also ich habe zwei Fragen:
Was genau %zd
und %tu
bedeuten?
Und ist es sicher zu verwenden %zd
und %tu
anstelle der Äpfel Vorschlag zur Typumwandlung zu lange?
Ich bin mir bewusst, ähnliche Fragen und Apples 64-Bit-Übergang-Führungen, die allen empfehlen, die %lu (unsigned long)
Ansatz. Ich Frage für eine alternative zum type-casting.
- Was ist mit @"%i". Ich denke, dass es funktionieren wird)
%i
entspricht genau%d
und hier nicht helfen. Leider gibt es keine format-specifier für NS(U)Integer.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Vom http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html:
Gibt an, dass eine nach [...] umwandlungsspezifikator gilt für eine
size_t
oder die entsprechende Ganzzahl Typ des Arguments;Gibt an, dass eine nach [...] umwandlungsspezifikator gilt für eine
ptrdiff_t
oder die entsprechenden unsigned-Typ-argument;Und von http://en.wikipedia.org/wiki/Size_t#Size_and_pointer_difference_types:
size_t
zur Darstellung der Größe aller Objekte (inklusive arrays), die in der bestimmten Implementierung. Es dient als Rückgabetyp dersizeof
Betreiber.ptrdiff_t
zur Darstellung der Differenz zwischen den Zeigern.Auf dem aktuellen OS X-und iOS-Plattformen haben wir
wo
__SIZE_TYPE__
und__PTRDIFF_TYPE__
sind vorgegeben durch diecompiler. Für 32-bit-compiler definiert
- und für 64-bit-compiler definiert
(Dies kann sich geändert haben, die zwischen Xcode-Versionen. Motiviert durch @user102008 ist
Kommentar, ich habe dieses mit Xcode 6.2 und aktualisiert die Antwort.)
So
ptrdiff_t
undNSInteger
sind beide typedef würde, um die gleichen Typ:int
auf 32-bit-undlong
auf 64-bit. Daherrichtig arbeiten und kompilieren, ohne Warnhinweise auf allen aktuellen
iOS-und OS X-Plattformen.
size_t
undNSUInteger
haben die gleiche Größe auf allen Plattformen, aberSie sind nicht vom gleichen Typ, so
gibt tatsächlich eine Warnung beim kompilieren für 32-bit.
Aber diese Beziehung ist nicht fest in jedem standard (soweit ich weiß), von daher würde ich
nicht halte es für sicher (im gleichen Sinn, wie die Annahme, dass
long
hat die gleiche Größeals Zeiger ist nicht als sicher betrachtet). Es brechen könnte in der Zukunft.
Die einzige alternative zur Typumwandlung, die ich kenne, ist von der Antwort auf die Frage "Stiftung Typen beim kompilieren für die arm64-und 32-bit-Architektur", Verwendung von Präprozessor-Makros:
zd
undtu
. Ich denke, ich bleibe mit Typ-casting dann die #define-Sachen sieht das noch schlimmer.long
/unsigned long
, aber warum gibt es eine Warnung bei der Verwendung von%ld
/%lu
ohne cast? Auch%zu
generiert eine Warnung, auch wenn Sie sagen, es sollte funktionieren ähnlich wie%tu
.ptrdiff_t
undNSInteger
sind beide typedef würden auf den gleichen Typ (int oder long). Ich habe aktualisiert die Antwort entsprechend. Und ja,NSLog(@"%zu", u);
generiert eine Warnung, die auf 32-bit. Vielleicht habe ich nicht, überprüfen Sie es richtig, oder, dass sich seit damals verändert. Und ich Frage mich, warumNSLog(@"%zd", i);
macht nicht eine Warnung generieren, die auf 32-bit.Ich bevorzugen, verwenden Sie einfach einen
NSNumber
statt:Diese funktioniert nicht in allen Situationen, aber ich habe ersetzt die meisten meiner NS(U)Integer Formatierung mit den oben genannten.
Laut Gebäude 32-bit-Wie 64-bit, eine andere Lösung zu definieren, die
NS_BUILD_32_LIKE_64
makro, und dann können Sie einfach die%ld
und%lu
Planern mitNSInteger
undNSUInteger
ohne casting und ohne Warnungen.