我是一名具有很少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 */
答案 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位有符号整数,除非您明确定义它。这可能就是这里发生的事情。