Apple现在要求所有iOS代码都是32/64位二进制代码。这很好 - 除了他们的一些库不完全支持二元性。
e.g。一个项目使用NSScanner,它支持“scanInteger”(正确)但没有“scanCGFloat” - 而是你必须“scanFloat”或“scanDouble”(用方法名称编码!)。
更新:NSScanner是一个比我意识到的更糟糕的例子;它需要指针作为args。
- (BOOL)scanFloat:(float *)result;
- (BOOL)scanDouble:(double *)result;
...啊。
它会影响一大堆东西 - 另一个例子是math.h(类似:float vs double在函数名中编码),虽然你可以至少切换到tgmath.h并摆脱“type-is这个名字“愚蠢。”
这个问题的正确,一般的解决方案是什么?
答案 0 :(得分:6)
C11引入了一项可用于“通用选择”的新功能
让编译器选择正确的方法,具体取决于CGFloat
的类型。
写为NSScanner
类别方法:
@implementation NSScanner (MyCategory)
-(BOOL) myScanCGFloat:(CGFloat *)cgFloatValue
{
return _Generic(*cgFloatValue,
double: [self scanDouble:(double *)cgFloatValue],
float: [self scanFloat:(float *)cgFloatValue]);
}
@end
说明:
_Generic
关键字在C11标准(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)的“6.5.1.1通用选择”中描述。另一种描述如下:
http://www.robertgamble.net/2012/01/c11-generic-selections.html。 CGFloat
是否与float
或double
兼容,
不是当前目标体系结构是32位还是64位。_Generic
关键字,即使在默认的GNU99模式下也是如此。我没有测试过早期的Xcode / Clang版本。 上一个回答: 一种可能的解决方案是模仿CGFloat
的定义
并让预处理器选择正确的版本:
CGFloat f;
#if __LP64__
[scanner scanDouble:&f];
#else
[scanner scanFloat:&f];
#endif
或者您定义自定义宏:
#if __LP64__
#define scanCGFloat scanDouble
#else
#define scanCGFloat scanFloat
#endif
// ...
CFFloat f;
[scanner scanCGFloat:&f];
或者,使用临时变量:
double tmp;
[scanner scanDouble:&tmp];
f = tmp;
答案 1 :(得分:1)
供参考(我觉得这是一个糟糕的,狡猾的解决方案),到目前为止,我最好的想法是:
注意 - 我正在使用NSScanner作为示例,但这是一个普遍的问题/解决方案!
if( sizeof( var ) <= 4 )
[scanner scanFloat:&var];
else
[scanner scanDouble:&var];
...但这不会修复编译器错误(在两个平台上),它只会使它“在运行时做正确的事情”作为黑客攻击。肯定不是一个好的解决方案?
答案 2 :(得分:1)
啊,在标题中路由,我刚发现这个(在Apple的官方“升级到64位”文档中不是mentioend !!!)
#define CGFLOAT_IS_DOUBLE 1
#define CGFLOAT_IS_DOUBLE 0
...所以我猜这是用的东西?
答案 3 :(得分:0)
最简单的解决方案是扫描为double,然后将结果转换为CGFloat。
-(CGFloat) scanCGFloat
{
double myDouble;
[scanner scanDouble: &myDouble];
return (CGFloat) myDouble;
}
对NSInteger和NSUInteger使用类似的技巧,始终扫描为(无符号)长并转换为NS(U)整数。