8

为 arm64 编译我的 iOS 应用程序代码时,我遇到了一个有趣的问题,与自定义 Foundation 类型的不同基本类型有关。假设我想打印一个声明为NSUInteger的数字(或 stringWithFormat)

[NSString stringWithFormat:@"%u", _depth,

这将产生一个针对 arm64 编译的警告,因为 NSUInteger 对 arm64 声明为 unsigned long。因此,我应该将“%u”替换为“%lu”,但现在这在为 armv7(s) 架构编译时变得无效,因为对于 32 位架构,NSUInteger 声明为 unsigned int。我知道警告说“NSUInteger 不应用作格式参数”,所以让我们继续浮动:

typedef CGFLOAT_TYPE CGFloat;

在 64 位CGFLOAT_TYPE上是double,而在 32 位上是float。因此,做这样的事情:

- (void)foo:(CGFloat)value;

接着

[self foo:10.0f]; 
[self foo:10.0]; 

编译两种架构时仍会产生警告。在 32 位架构上,第二次调用不正确(从 double 转换为 float),在 64-bt 架构上,第一次调用将 float 转换为 double(没关系,但仍然不好)。

很想听听您对这个问题的看法。

4

1 回答 1

11

我见过的一种(不可否认的糟糕)方法是使用#define和编译时字符串文字连接的魔力。像这样:

// In your prefix header or something
#if __LP64__
#define NSI "ld"
#define NSU "lu"
#else
#define NSI "d"
#define NSU "u"
#endif

// Then later you can use these like this...
NSString* foo = [NSString stringWithFormat:@"%"NSU" things in the array.", array.count]);

非常可怕,但它有效。

另一种看似更常见的方法是简单地将值向上转换为每个平台上的较大类型,如下所示:

NSString* foo = [NSString stringWithFormat:@"%lu things in the array.", (unsigned long)array.count]);

最近(即自从新的拳击速记语法问世以来)我发现自己很懒惰并开始对所有东西进行拳击,就像这样:

NSString* foo = [NSString stringWithFormat:@"%@ things in the array.", @(array.count)]);

可能有更好的方法,但这些是我见过最多的方法。

于 2013-09-17T11:47:14.890 回答