2015-04-07 67 views
0

我正在寫一個非常基本的程序來打印在C語言(0到((2^n) - 1)中的變量的無符號long long的範圍,其中其中n是任何系統中的數據類型的位數(根據編譯器安裝C)在我的系統中,長變量的長度爲8字節。代碼:在C編程語言中使用pow()函數時的警告消息

#include<stdio.h> 
#include<math.h> 

int main() 
{ 
    unsigned long long n; 

    //n = pow(2, 63); 
    //n = (n * 2) - 1; 
    n = pow(2, 64) - 1;  

    printf("\nn: %llu\n", n); 

    return 0; 
} 

編譯時,GCC給了我以下錯誤:

Print_long_long_int.c:10:2:警告:在隱式常量轉換中溢出[-Woverflow]。

上執行它,我得到的 n個正確的輸出:18446744073709551615

但是,如果我請從行單意見,並使用它們:

n = pow(2, 63); 
n = (n * 2) - 1; 

相反的:

n = pow(2, 64) - 1; 

它不給我任何這樣的警告。並正常執行。 這種差異爲什麼會發生?

謝謝!

+2

那麼很可能意味着GCC並沒有叫'POW()'在運行,但正在評估不斷在編譯的時候,它注意到'POW(2,64)'是太大,無法進入64無符號整數,但不拒絕完成編譯,並設法通過一些或多或少的迂迴手段來得到正確的答案。其他編譯器或GCC的優化次數可能會有所不同。 –

+0

'pow'根本就不是任務的正確工具,它使用'double'而不是整數類型。所以在任何時候你都可能會失去精確性。使用移位運算符'<<'來獲得'2'的大功率。但即使如此,如果你的類型只有64位,你顯然無法獲得高於63的能力。 –

回答

3

當你給

pow(2,64) -1 ; 

超過的無符號的限制很長很長。這是你得到這個警告的原因。

的無符號長範圍是pow(2,64)184467440737095516160 to 18,446,744,073,709,551,615

結果。

+0

如果是這樣,爲什麼要這樣寫:'n = pow(2,63); n =(n * 2)-1';作品?因爲執行這兩行給出了** n:18446744073709551615 **的正確答案。如果** unsigned long long **的大小較小,這兩行不應該彈出警告消息嗎? – Arun

0

電源應該返回一個整數,並且你得到一個無符號long long。我只是做了一個簡單的函數來處理未簽名的long long。

#include<stdio.h> 

unsigned long long power(int base, int exponent) 
{ 
    unsigned long long n = 1; 
    int i; 
    for (i = 0; i < exponent ; i++) 
     n *= base; 

    return n; 
} 

int main() 
{ 
unsigned long long n = power(2, 64) - 1; 
printf("n: %llu\n", n); 

return 0; 
} 
+0

不應** ** unsigned long long n = 1 **(在「power」的函數定義中),因爲如果它爲0,則整個產品將計算爲0. – Arun

+0

是的,您是對的。我急着寫這個,犯了一個粗心的錯誤。 – ProfOak