2013-10-10 22 views
6

ここでの回答の助言と​​して、私は私のコードは、任意の悪い行動のgccがキャッチすることができたかどうかを確認するために-Wbad-function-castをオンにし、それはこの例を上げ: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を幸せにするために、あなたのコードを書き換えるしようとした場合-O3であっても、最近のGCC/Clang compilers don't optimize awayを呼び出します。

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

(負例、-Wbad-function-castno warning emittedが、余分関数呼び出し)

5

この警告は深刻なものです。

powの浮動小数点結果から整数を取得する場合は、丸め演算です。これは、標準丸め関数の1つ、たとえばroundで行う必要があります。整数キャストでこれを行うと、驚くべきことが起こるかもしれません。小数部分が一般に緩くなり、たとえば2.76は、2となるように、2.12と同じように整数切り捨てで2となることがあります。この動作が必要な場合でも、floor機能で明示的に指定する方がよいでしょう。これにより、コードの可読性とサポート性が向上します。

+0

はい、私はその動作が欲しいので、私はキャストしています。私は 'floor'を追加するとコードが遅くなることに気付きました。特に 'cvttsd2si'ではなく、' roundsd'、そして 'cvttsd2si'を-O3で取得します。これは私のために何かしますか? (私はパフォーマンスペナルティを支払うつもりです - このアプリケーションは速度に敏感ですが、この特定の部分はホットループの外にありますが、それが何か価値がある場合のみ) – Charles

+0

1つの具体的なアーキテクチャと(2)あなたがここで打ち切ることで何をしているのか理解していれば、この警告を無視するかオフにすることができます。クロスプラットフォーム互換性と丸めの問題について警告するために、C言語で発行されています。また、powのdouble結果が最大整数値をオーバーフローした場合、キャスト動作は未定義ですが、フロア動作は常に指定されます。 –

+0

私は、オーバーフローが未定義の動作をもたらすことに同意します。これは悪いことです。 (これが私のサンプルコードを与えた理由です - ここではオーバーフローが不可能であることがわかります)。ありがとう、私は今受け入れています。 – Charles

関連する問題