2013-03-18 17 views
1

所以,我下面的代碼,我知道這是什麼地方壞,我根本無法查明...有趣,真的很煩人整數問題

static uint64_t get_disk_total(const char* path) 
{ 
    struct statvfs stfs; 
    if (statvfs(path, &stfs) == -1) 
    { 
     return 0; 
    } 
    uint64_t t = stfs.f_blocks * stfs.f_bsize; 
    std::cout << "total for [" << path << "] is:" << t 
       << " block size (stfs.f_bsize):" << stfs.f_bsize 
       << " block count (stfs.f_blocks):" << stfs.f_blocks 
       << " mul:" << stfs.f_blocks * stfs.f_bsize 
       << " hardcoded: " << (uint64_t)(4096 * 4902319)  // line 50 
       << std::endl ; 
    return t; 
} 

當我編譯它,告訴我:

part_list.cpp: In function ‘uint64_t get_disk_total(const char*)’: 
part_list.cpp:50:59: warning: integer overflow in expression [-Woverflow] 

好。當我運行它,結果是(換行手動添加):

total for [/] is:2900029440 
block size (stfs.f_bsize):4096 
block count (stfs.f_blocks):4902319 
mul:2900029440 
hardcoded: 18446744072314613760 

我知道,那4902319 * 4096 = 20079898624 ... google告訴我這是。那麼我怎麼得到第一個2900029440然後18446744072314613760爲同樣的計算?有人能解釋我在這裏發生了什麼嗎?這是我現在的綜合能力之上,我覺得,這是一個隱藏的小小問題... 4902319 * 4096不應該是這樣一個巨大的數字,應用程序像這樣瘋狂......

謝謝你你的幫助!

+5

Try(uint64_t)(4096)*(uint64_t)(4902319)。如果你讓它按照原樣行事,它會將你的INT表達式轉換爲uint64_t結果,而不是做一個64位操作 – Turgal 2013-03-18 10:08:12

回答

6

首先你計算(4096 * 4902319)這是計算爲int它溢出。 然後這個數字被轉換爲uint64_t

嘗試:

(4096 * (uint64_t) 4902319) 

爲了使計算爲uint64_t中。

+1

這解釋了它:''uint64_t t =(uint64_t)stfs.f_blocks *(uint64_t)stfs.f_bsize; '是解決神祕的正確方法......謝謝! – fritzone 2013-03-18 10:11:52

+0

這是從C++ 03開始的一個有趣的變化。在C++ 03中,溢出表達式使得程序不合格,並且需要診斷。 (我想知道爲什麼這被轉換爲C++ 11中的未定義行爲。) – 2013-03-18 10:13:26

1

使用無符號長長文字:

4096 * 4902319ULL 
       ~~~ 

計算溢出之前。