2013-10-10 58 views
6

誠如通過這裏的答案,我打開-Wbad-function-cast,看看我的代碼有什麼不良行爲的gcc能趕上,它打開了這個例子:gcc的-Wbad-function-cast的目的是什麼?

unsigned long n; 
// ... 
int crossover = (int)pow(n, .14); 

(這不是這裏的關鍵是crossoverint ;它可能是unsigned long,消息將是相同的)。

這似乎是一個非常普通且有用的演員示例。爲什麼這是有問題的?否則,是否有理由保持此警告開啓?

我一般都喜歡設置很多警告,但是我無法圍繞這個用例進行思考。我正在處理的代碼數值很大,並且有很多次將事情從一種類型轉換爲另一種類型,以滿足所涉及算法的不同需求。

回答

1

-Wbad-function-cast警告的用途是有限的。

可能,-Wall-Wextra都不會啓用該警告。它不適用於C++(僅限於C/Objective-C)。

您的具體示例不會利用未定義的行爲或實現定義的行爲(參見ISO C11,第6.3.1.4節)。因此,這個警告給你零利益。

相反,如果你試圖重寫你的代碼,使-Wbad-function-cast快樂你只需要添加多餘的函數調用,即使最近GCC/Clang compilers don't optimize away-O3

#include <math.h> 
#include <fenv.h> 
int f(unsigned n) 
{ 
    int crossover = lrint(floor(pow(n, .14))); 
    return crossover; 
} 

(反面教材,no warning emitted-Wbad-function-cast但多餘的函數調用)

5

你最好認真對待這個警告。

如果要從pow的浮點結果中獲取整數,它是舍入操作,必須使用標準舍入函數之一來完成,例如round。使用整型轉換可能會產生驚喜:通常會丟失小數部分,例如2.76可能會以整數截斷結尾爲2,就像2.12會以2結束一樣。即使你想要這種行爲,你最好用floor函數明確指定它。這將增加您的代碼的可讀性和可支持性。

+0

是的,我想要這種行爲,這就是爲什麼我要投。我注意到,當我添加「floor」時,代碼變慢;特別是,我得到'roundsd'然後''cvttsd2si'在-O3而不是簡單地'cvttsd2si'。這對我有幫助嗎? (我願意支付性能損失 - 雖然這個應用程序對速度敏感,但這個特定部分不在熱循環之內 - 但僅限於它會做一些有價值的事情。) – Charles

+0

如果您是(1)瞄準一個具體的體系結構和(2)明白你在做什麼截斷鑄造在這裏,然後你可以忽略或關閉這個警告。它在C中發佈,以警告跨平臺兼容性和舍入問題。另外,如果pow的double結果溢出最大整數值,那麼投影行爲是未定義的,而樓層行爲總是被指定的。 –

+0

我同意溢出會給未定義的行爲,這是一件壞事。 (這就是爲什麼我給我的示例代碼 - 你可以看到溢出在這裏是不可能的。)謝謝,我現在接受。 – Charles