繁体   English   中英

ObjectiveC测试int是否为long / CGFloat是float还是double

[英]ObjectiveC test if int is long or not / CGFloat is float or double

Apple现在要求所有iOS代码都是32/64位二进制。 这很好 - 除了他们的一些库不完全支持二元性。

例如,一个项目使用NSScanner,它支持“scanInteger”(正确)但不支持“scanCGFloat” - 而是必须“scanFloat”或“scanDouble”(以方法名称编码!)。


更新:NSScanner是一个比我意识到的更糟糕的例子; 它需要指针作为args。

- (BOOL)scanFloat:(float *)result;
- (BOOL)scanDouble:(double *)result;

...啊。


它会影响一大堆东西 - 另一个例子是math.h(类似地:float vs double在函数名中编码),虽然你可以至少切换到tgmath.h并摆脱“type-is-in-这个名字“愚蠢。

什么是这个问题的正确,一般的解决方案?

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标准的“6.5.1.1通用选择”中描述( http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf )。 另一种描述如下: http//www.robertgamble.net/2012/01/c11-generic-selections.html
  • 选择匹配代码由编译器完成,而不是在运行时完成。
  • 选择检查CGFloat是否兼容floatdouble ,而不是当前目标体系结构是32位还是64位。
  • 此解决方案不依赖于任何预处理器宏。
  • 从Xcode 5.0.2开始,即使在默认的GNU99模式下,Clang也支持_Generic关键字。 我没有测试过早期的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;

作为参考(我觉得这是一个糟糕的,cludgy解决方案),到目前为止我最好的想法是:

注意 - 我正在使用NSScanner作为示例,但这是一个普遍的问题/解决方案!

if( sizeof( var ) <= 4 )
    [scanner scanFloat:&var];
else
    [scanner scanDouble:&var];

...但这不会修复编译器错误(在两个平台上),它只会使它“在运行时做正确的事情”作为黑客攻击。 肯定不是一个好的解决方案?

啊,在标题中路由,我刚发现这个(不是苹果官方“升级到64位”文档中的mentioend !!!)

#define CGFLOAT_IS_DOUBLE 1

#define CGFLOAT_IS_DOUBLE 0

...所以我猜这是用的东西?

最简单的解决方案是扫描为double,然后将结果转换为CGFloat。

-(CGFloat) scanCGFloat
{

    double myDouble;
    [scanner scanDouble: &myDouble];
    return (CGFloat) myDouble;
}

对NSInteger和NSUInteger使用类似的技巧,始终扫描为(无符号)长并转换为NS(U)整数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM