2011-12-07 115 views
13

我是一個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妥善投給相關雙重價值,但更大的數字(我測試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

什麼是dispatch_time的參數? – Pubby

+0

謝謝@Pubby,我已經更新了這個問題。 –

+0

這似乎很奇怪,1,2工作和3,4不...我會仔細檢查,但你肯定會看到整數將評估爲0f的情況。 –

回答

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溢出,導致值爲se t爲0.

編輯:我大概已經可以更好地說明上述說法。溢出可能導致int(假設它的大小爲32位,如上所述)等於值-294967296,並且dispatch_time將把任何值<= 0視爲0秒。這就是上面「0」的來源。

A double變量可以保存比int更大的值,並且能夠存儲值4000000000的近似值。

+0

非常明確的答案感謝。 :) –

+1

正確地點上。 +1。 –

+1

當計算溢出時,您將環繞而不是零。這裏的值可能會<0,並且派遣可能將其視爲'立即執行'。 –

7

前兩個工作,因爲1 * 10^9和2 * 10^9符合一個有符號的32位整數。但是,4 * 10^9不適合有符號的32位整數。

4.0 * 10^9可以工作,因爲浮點可以表示該值。

我希望這將工作太:

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

我一無所知目標C,但我的猜測是,4 * NSEC_PER_SEC太大了32位整數。通過使用4.0,您可以將乘法強制爲浮點算術並解決問題。

更新

這可能是64位代碼,但在一些語言(我知道C#是一個)數字文字默認爲32位有符號整數,除非你明確地定義它,否則。這可能是這裏發生的事情。

+0

謝謝,「NSEC」是納秒,所以它是一個很大的數字。我用它的定義更新了我的問題。順便說一句,這是所有64位代碼,但我不知道這是否有所作爲。 –

+0

查看我更新的答案。 –

+0

是的,在32位UNIX或64位UNIX上,int是32位 –