编译arm64和32位体系结构时的基础类型
编译我的iOS应用程序的arm64代码我遇到了一个有趣的问题,与自定义Foundation类型的不同基本类型有关。 假设我想要printf(或stringWithFormat)声明为NSUInteger的数字
[NSString stringWithFormat:@"%u", _depth,
这将为arm64生成一个警告编译,因为NSUInteger为arm64声明为unsigned long。 因此,我应该用“%lu”替换“%u”,但现在在编译armv7(s)体系结构时这变得无效,因为对于32位体系结构,NSUInteger声明为unsigned int。 我知道警告说“NSUInteger不应该用作格式参数” ,所以让我们继续浮动:
typedef CGFLOAT_TYPE CGFloat;
在64位CGFLOAT_TYPE上是双倍 ,而在32位上它是浮点数 。 因此,做这样的事情:
- (void)foo:(CGFloat)value;
接着
[self foo:10.0f]; [self foo:10.0];
在编译两个体系结构时仍会产生警告。 在32位架构上,第二次调用不正确(从double转换为float),在64-bt架构上,第一次将float转换为double(这是好的,但仍然不好)。
很想听听你对这个问题的看法。
我见过的一种(不可否认的)方法是使用#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)]);
可能有更好的方法,但那些是我见过的最多的方式。