2011-12-07 5 views
13

私はObjective-Cの開発者でC/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 

なぜ適切に関連するdouble値にキャスト1と2の操作を行いますが、より大きな数字は(私は3テストおよび4)は0として表現されるように見えますか?

私は、LLVM 3.0を使用するように設定されたXcode 4.2でコンパイルしています。

EDIT:

dispatch_time_tを次のように定義される。

typedef uint64_t dispatch_time_t; 

そしてdispatch_timeである:1ため

#define NSEC_PER_SEC 1000000000 /* nanoseconds per second */ 
+0

dispatch_timeのパラメータは何ですか? – Pubby

+0

Thanks @Pubby、私は質問を更新しました。 –

+0

1,2の作業と3,4はそれほど奇妙に思われます...私はそれを二重にチェックしますが、intが0fと評価されるインスタンスは確かにあります。 –

答えて

25

1秒間に1,000,000,000ナノ秒があるので、NSEC_PER_SEC1000000000と定義されています。

  • 4タイプのint
  • 4.0である今では、したがって、intは32ビットを含む、intの範囲は[-2,147,483,648 to 2,147,483,647]

    4000000000 > 2147483647であろうと仮定型のdouble

ありますintがオーバーフローし、値がseになる原因になります0から

編集:私はおそらく上記のステートメントをより良い言葉にしている可能性があります。オーバーフローにより、-294967296の値に等しくなるようにint(前述のように32ビットのサイズであると仮定する)が発生し、dispatch_timeは任意の値<= 0を0秒として処理します。それは上の "0"がどこから来たかです。

double変数は、intより大きい値を保持でき、値4000000000の近似値を格納できます。

+0

完全に明確な答えをありがとう。 :) –

+1

正確に上にスポット。 +1。 –

+1

計算がオーバーフローすると、ゼロではなくラップアラウンドします。ここの値はおそらく<0であり、発送は恐らくそれを「すぐに行う」と扱っているでしょう。 –

7

最初の2つのワーク:

dispatch_time_t dispatch_time(dispatch_time_t when, int64_t delta); 

そしてNSEC_PER_SECであります* 10^9符号付き32ビットintには2 * 10^9が入ります。しかし、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

は、私はObjective Cのについて何も知らないが、私の推測では、4 * NSEC_PER_SECは、32ビットの整数には大きすぎるということです。 4.0を使用すると、乗算が浮動小数点演算に強制され、問題を回避できます。

更新

あなたが明示的にそれを定義しない限り、それは32ビット符号付き整数に数値リテラルをデフォルトの64ビットコードであるが、いくつかの言語で(と私はC#は1である知っている)ことがあります。それはここで起こっているかもしれません。

+0

ありがとうございます。「NSEC」はナノ秒ですので、大きな数字です。私はそれの定義で私の質問を更新しました。ちなみに、これはすべて64ビットコードですが、違いがあるかどうかはわかりません。 –

+0

私の更新された回答を参照してください。 –

+0

はい、32ビットUNIXまたは64ビットUNIXの場合、intは32ビットです –

関連する問題