2

以下のコードで「if (sqrt)」条件が常に true になるのはなぜですか? コンパイル時に、gcc は次のように警告します。

weak.c: In function âfâ:
weak.c:6: warning: the address of âsqrtâ, will always evaluate as âtrueâ

ソースコード,</p>

#include <stdio.h>

extern double sqrt(double x); /* DECLARATION VERSION 1 */
/* extern double sqrt(double x) __attribute__ ((weak)); */ /* DECLARATION VERSION 2 */

void f() {
        if (sqrt) {
                printf("sqrt of 10 %f \n", sqrt(10.0));
        }
        else {
                printf("sqrt not found \n");
        }
}

int main (int arg, char **argv)
{
        f();
        return 0;
}

行「DECLARATION VERSION 1」をコメントアウトし、行「DECLARATION VERSION 2」のコメントを外すと、以下の動作をするバイナリができます。

  • バイナリが -lm でリンクされている場合、「if (sqrt)」は true です。
  • そうでない場合、条件は false です。私は弱いシンボルを知っている/考えています。これが「sqrt」関数です。リンク時に0で初期化されます。したがって、「sqrt」シンボルが他の場所 (ライブラリ) でその定義を見つけることができない場合、「if (sqrt)」条件は false です。

しかし、「DECLARATION VERSION 1」を使用すると、「sqrt」が常にゼロ以外になるのはなぜですか? 「DECLARATION VERSION 1」では、「sqrt」は弱い記号ではなく、もちろん強い記号でもありません。実際、「nm」コマンドを使用すると、「sqrt」記号が見つかりません。さらに、「sqrt」のアドレスを出力しようとすると、コンパイル エラーが発生します。

「sqrt」がゼロでない理由を誰かが知っていますか?

前もって感謝します!

質問を説明する適切なタイトルが見つからないため、より適切なタイトルを提案してください。

私はその理由を見つけたと思います:

gcc には、最適化のために組み込みの sqrt() 関数があります。可能であれば、gcc は libm の sqrt() の呼び出しを組み込みの sqrt() に置き換えます ( http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html ) 。コンパイル時に、組み込み関数がオフになっておらず、libm(-lm) が指定されていない場合、gcc は常にゼロ以外のアドレスを持つ sqrt() の組み込みバージョンを使用します。組み込みをオフにすると、コンパイル エラーが発生します

$ gcc -fno-builtin weak.c
weak.c: In function âfâ:
weak.c:9: warning: the address of âsqrtâ, will always evaluate as âtrueâ
/tmp/cc84fwK9.o: In function `f':
weak.c:(.text+0x11): undefined reference to `sqrt'
weak.c:(.text+0x29): undefined reference to `sqrt'
collect2: ld returned 1 exit status
4

1 に答える 1