ARM64和32位体系结构编译时的基础类型 编译我的iOS应用程序的代码为ARM64,我遇到了一个有趣的问题,涉及到自定义基础类型的不同基本类型。假设我想打印F(或stringWithFormat)一个声明为NSInteger的数字 [NSString stringWithFormat:@"%u", _depth,

ARM64和32位体系结构编译时的基础类型 编译我的iOS应用程序的代码为ARM64,我遇到了一个有趣的问题,涉及到自定义基础类型的不同基本类型。假设我想打印F(或stringWithFormat)一个声明为NSInteger的数字 [NSString stringWithFormat:@"%u", _depth,,ios,objective-c,c,types,printf,Ios,Objective C,C,Types,Printf,这将为arm64生成一个警告,因为对于arm64,整数声明为无符号长。因此,我应该将“%u”替换为“%lu”,但现在在为armv7(s)体系结构编译时,这将变得无效,因为对于32位体系结构,整数声明为unsigned int。 我知道警告说“不应将NSUInteger用作格式参数”,所以让我们继续浮点数: typedef CGFLOAT_TYPE CGFloat; 在64位上,CGFLOAT\U类型为双精度,而在32位上为浮点型。因此,这样做: - (void)foo:(CGFloat)val

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

typedef CGFLOAT_TYPE CGFloat;
在64位上,CGFLOAT\U类型为双精度,而在32位上为浮点型。因此,这样做:

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

[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]);
很可怕,但它能起作用

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

- (void)foo:(CGFloat)value;
NSString* foo = [NSString stringWithFormat:@"%lu things in the array.", (unsigned long)array.count]);
NSString* foo = [NSString stringWithFormat:@"%@ things in the array.", @(array.count)]);
最近(即,自从新的拳击速记语法问世以来),我发现自己很懒,开始拳击所有东西,如下所示:

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

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

也许应该提到的是,上溯只是形式化的(为了让编译器满意),但实际上并没有改变任何东西,因为在32位和64位体系结构上,
sizeof(unsigned long)==sizeof(nsuiger)
。自动完成建议完全上溯(即%lu和(无符号长)值)我很困惑。你如何在编译时定义
NSI
/
NSU
,然后神奇地在运行时为每个体系结构选择正确的一个呢?选择不是在运行时发生的。所有的选择都是在编译时发生的。
NSInteger
NSUInteger
也在编译时定义,这只是m我正在模仿/并行这种行为。你真的收到了
[self-foo:10.0f]
的警告吗?即使使用
-Weverything
,我也无法重现这种警告。如果你阅读苹果的64位转换指南,他们建议对printf样式的格式字符串进行强制转换。