Int to Double cast问题

时间:2011-12-07 23:05:02

标签: objective-c c cocoa grand-central-dispatch

我是一名具有很少C / C ++经验(并且没有培训)的Objective-C开发人员,今天我遇到了一些奇怪的硬编码数值。

我确定这是一个简单/愚蠢的问题,但有人可以解释一下为什么会这样:

NSDate *start = [NSDate date];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC);

dispatch_after(popTime, dispatch_get_main_queue(), ^{
  NSLog(@"seconds: %f", [start timeIntervalSinceNow]);
});
// output: seconds: -1.0001

这也有效(注意秒数已经改变):

NSDate *start = [NSDate date];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);

dispatch_after(popTime, dispatch_get_main_queue(), ^{
  NSLog(@"seconds: %f", [start timeIntervalSinceNow]);
});
// output: seconds: -2.0001

但这是立即执行的:

NSDate *start = [NSDate date];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 4 * NSEC_PER_SEC);

dispatch_after(popTime, dispatch_get_main_queue(), ^{
  NSLog(@"seconds: %f", [start timeIntervalSinceNow]);
});
// output: seconds: -0.0001

但是,使用4.0代替4修复了它:

NSDate *start = [NSDate date];
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 4.0 * NSEC_PER_SEC);

dispatch_after(popTime, dispatch_get_main_queue(), ^{
  NSLog(@"seconds: %f", [start timeIntervalSinceNow]);
});
// output: seconds: -4.0001

为什么1和2正确地转换为相关的double值,但是更大的数字(我测试3和4)似乎表示为0

我正在使用Xcode 4.2进行编译,配置为使用LLVM 3.0。

编辑:

dispatch_time_t定义为:

typedef uint64_t dispatch_time_t;

dispatch_time是:

dispatch_time_t dispatch_time(dispatch_time_t when, int64_t delta);

NSEC_PER_SEC是:

#define NSEC_PER_SEC    1000000000  /* nanoseconds per second */

3 个答案:

答案 0 :(得分:25)

一秒钟内有1,000,000,000纳秒,所以我假设NSEC_PER_SEC被定义为1000000000

  • 4的类型为int
  • 4.0的类型为double

现在假设int包含32位,int的范围为[-2,147,483,648 to 2,147,483,647]

4000000000 > 2147483647,因此您将导致int溢出,这会导致该值设置为0.

编辑:我可能会更好地表达上述声明。溢出可能导致int(假设它的大小为32位,如上所述)等于值-294967296,而dispatch_time将任何值<= 0视为0秒。这就是上面“0”的来源。

double变量可以包含比int更大的值,并且能够存储值4000000000的近似值。

答案 1 :(得分:7)

前两个工作因为1 * 10 ^ 9和2 * 10 ^ 9符合有符号的32位int。但是,4 * 10 ^ 9将不适合带符号的32位int。

4.0 * 10 ^ 9有效,因为浮点数可以表示该值。

我希望这也会奏效:

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, ((int64_t)4) * NSEC_PER_SEC);

答案 2 :(得分:2)

我对Objective C一无所知,但我的猜测是4 * NSEC_PER_SEC对于32位整数来说太大了。通过使用4.0,您可以将乘法强制转换为浮点运算并解决问题。

<强>更新

它可能是64位代码,但在某些语言中(我知道C#是1),数字文字默认为32位有符号整数,除非您明确定义它。这可能就是这里发生的事情。