11

私は最近、ac プログラムを書く gcc 3.2.2 の次の動作に出くわしました:

if ステートメントで、関数の中かっこを忘れて次のように書きました。

if(myFunc)...それ以外のif(myFunc())...

ほとんどすべての警告をオンにしていますが、これはエラーも警告も生成しませんでした。

単純に と評価されましたtrue。そもそもなぜこれが合法的なコードを書いているのでしょうか? 関数が存在する/アドレスがあるためですか?そのような間違いを回避する方法や、私が見落とした警告オプションがあるかどうかを知っている人はいますか? この問題は、後の gcc バージョンでより適切に解決されていますか?

完全を期すための正確なコンパイラ呼び出しは次のとおりです。

 msp430-gcc -g -Os -mmcu=msp430x1611 -Wall -W -Wfloat-equal -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wwrite-strings -Wsign-compare -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations 
-Wredundant-decls -Wnested-externs -Wimplicit-function-declaration -Werror

(私は gcc 3.2.3 を使用せざるを得ないため、-Wextra はありません)

4

5 に答える 5

17

if (myFunc)と同等なif (&myFunc)ので、関数のアドレスをテストしています。もちろん、これは常にゼロ以外、つまり true になります。

gcc 4.2.1-Wallでは、次の警告が表示されます。

myfunc.c:11: warning: the address of ‘myFunc’ will always evaluate as ‘true’

于 2010-12-01T19:27:11.357 に答える
3

myFuncは単に関数のメモリアドレスであり、ゼロではありません。

あなたのifステートメントは、書くこととほとんど同じです:

if (0x08451234) { ... }

また、ゼロ以外の値として、それはtrueです。

関数ポインターをテストして NULL かどうかを確認することは有効であり、ある程度一般的であるため、警告は適切ではないようです。

于 2010-12-01T19:31:54.223 に答える
1

myFunc、関数の名前は常に評価されるtrueため、ポインターであるためです。より具体的に、逆参照する必要があるため、null 以外のポインターである必要があります。nullポインターは に評価されますfalse

要するに、コンパイラが間違いを犯したことを知らせる方法はないようです。

あなたがする必要があるのは、実際に関数を呼び出したことを伝えることができるように、trueとの応答を別々に呼び出すいくつかの単体テストを用意することです。false

于 2010-12-01T19:46:50.463 に答える
0

関数へのポインターは、ソート ルーチンやデータ キャプチャなどのコールバックとして役立つ場合があります。または、C にはテンプレートがないため、最適化された計算された goto 型ルーチンを実行する場合。

しかし、99% の確率でエラーです。新しいコンパイラでは警告が表示されます。

于 2010-12-01T19:33:24.613 に答える
0

これは、古いリンカー ハックをサポートするためのものです。多くのコンパイラ/リンカー (gcc および GNU binutils を含む) では、リンクされた別のオブジェクト ファイル/共有ライブラリがシンボルの値をオーバーライドしない限り、0 に評価される関数の弱いシンボルを定義できます。glibc はこのトリックをいくつかのバージョン互換性ハックに利用しています。

于 2010-12-01T20:43:56.730 に答える