在32位和64位体系结构上格式化NS(U)Integer时types转换的替代方法?
使用64位版本的iOS,我们不能再使用%d
和%u
来格式化NSInteger
和NSUInteger
。 因为对于64位,这些是typedef'd long
和unsigned long
而不是int
和unsigned int
。
所以如果你尝试用%d格式化NSInteger,Xcode会抛出警告。 Xcode对我们来说很好,并为这两种情况提供了一种替代scheme,它由l前缀格式说明符和longtypes组成。 那么我们的代码基本上是这样的:
NSLog(@"%ld", (long)i); NSLog(@"%lu", (unsigned long)u);
如果你问我,这是一个痛苦的眼睛。
几天前,Twitter上有人提到了格式说明符%zd
来格式化签名variables和%tu
来格式化32和64位平台上的无符号variables。
NSLog(@"%zd", i); NSLog(@"%tu", u);
这似乎工作。 而我更喜欢types化。
但我真的不知道为什么这些工作。 现在这两个对我来说基本上都是神奇的价值。
我做了一些研究,发现z
前缀表示以下格式说明符与size_t
具有相同的大小。 但是我完全不知道前缀t
是什么意思。 所以我有两个问题:
%zd
和%tu
究竟是什么意思?
是否可以安全地使用%zd
和%tu
而不是Applebuild议将types转换为long?
我知道类似的问题和苹果64位转换指南,这些指南都推荐使用%lu (unsigned long)
方法。 我要求一个替代types铸造。
从http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html :
- ž
指定以下转换说明符适用于size_t
或相应的带符号整数types参数; - Ť
指定以下转换说明符适用于ptrdiff_t
或相应的无符号types参数;
从http://en.wikipedia.org/wiki/Size_t#Size_and_pointer_difference_types :
-
size_t
用于表示特定实现中任何对象(包括数组)的大小。 它用作sizeof
运算符的返回types。 -
ptrdiff_t
用来表示指针之间的差异。
在当前的OS X和iOS平台上
typedef __SIZE_TYPE__ size_t; typedef __PTRDIFF_TYPE__ ptrdiff_t;
其中__SIZE_TYPE__
和__PTRDIFF_TYPE__
由编译器预定义。 对于编译器定义的32位
#define __SIZE_TYPE__ long unsigned int #define __PTRDIFF_TYPE__ int
和编译器定义的64位
#define __SIZE_TYPE__ long unsigned int #define __PTRDIFF_TYPE__ long int
(这可能在Xcode版本之间有所变化,受@ user102008评论的启发,我已经用Xcode 6.2检查过了,并且更新了答案。)
所以ptrdiff_t
和NSInteger
都是typedef'd 相同的types : int
在32位和long
在64位。 因此
NSLog(@"%td", i); NSLog(@"%tu", u);
在所有当前的iOS和OS X平台上正常工作并编译时不会出现警告。
size_t
和NSUInteger
在所有平台上都有相同的大小,但是它们不是相同的types,所以
NSLog(@"%zu", u);
实际上在编译32位时会发出警告。
但是这个关系在任何标准上都是不固定的(据我所知),所以我不认为这是安全的(就像假设long
与指针的大小一样不被认为是安全的)。 它可能在未来破裂。
我所知道的唯一types转换的替代方法是使用预处理器macros从“ 编译为arm64和32位体系结构时的基础types ”的答案:
// In your prefix header or something #if __LP64__ #define NSI "ld" #define NSU "lu" #else #define NSI "d" #define NSU "u" #endif NSLog(@"i=%"NSI, i); NSLog(@"u=%"NSU, u);
我宁愿只是使用一个NSNumber
:
NSInteger myInteger = 3; NSLog(@"%@", @(myInteger));
这在所有情况下都不起作用,但是我用上面的代替了大部分NS(U)Integer格式。
根据构build32位像64位 ,另一种解决scheme是定义NS_BUILD_32_LIKE_64
macros,然后你可以简单地使用%ld
和%lu
说明符与NSInteger
和NSUInteger
没有铸造和没有警告。