2

重複の可能性:
-std=c99 が設定されている場合、gcc が random() インターフェイスを見つけられないのはなぜですか?

私はCに慣れていないので、 に入りman stdlib.h、「random」を検索し、それがrandom()返されるのを見てlong、それが単なる学習課題であるため、 int にキャストするだけだと思いました(わざわざ返されるものを探すのではなく)int-rand()です)。

とにかく、プログラムは正しくコンパイルされ、実行されます。しかし:

$ gcc -std=c99 part1.c
part1.c: In function 'main':
part1.c:44:5: warning: implicit declaration of function 'random'

-std=99フラグを外すと消えます。「問題のある」コードは次のとおりです。

  int test6[1000];
  for(i = 0; i < 1000; i++)
  {
    test6[i] = (int) random();
    printf("it is %d\n", test6[i]); //check random() is working (it isn't seeded)
  }
  printf("%d\n", largest(test6, 1000));

だから、面白いかもしれないと思ったので、誰かがこれがなぜなのか知っているのだろうかと思いました。

4

1 に答える 1

6

関数は使用前に宣言されていないため、warning: implicit function definitionメッセージが表示されます。random()これは標準の C 関数ではありません (ISO/IEC 9899:2011 またはその前身のバージョンではありません)。どのヘッダーがそれを宣言しているかを知る必要があります。#define宣言を可視化するために何かが必要になる場合があります。

C99 では、すべての関数を使用する前に宣言する必要があります。これがモード オブジェクトの理由-std=c99です (必須の診断を発行しても、コンパイルを続行できます。おそらく、関数が を返すという下位互換性の仮定を作成しますint)。C の古いバージョンでは、関数を事前に宣言する必要はありませんでした。宣言されていない関数は、暗黙のうちに として宣言されましたextern int function();。これは、「未指定の (ただし変数ではない) 引数リストを持つ関数がint' を返す」ことを意味します。それが、コンパイルがその仮定を続けている理由です。以前は、それが標準的な仮定でした。C99 と C2011 では、公式にはエラーです。


私の混乱は、プログラムがまだ正しくコンパイルされて実行されていることです(random()疑似乱数も返します)!#include <stdlib.h>ファイルの先頭にあります。私のが機能して#includeいない可能性はありますmakeが、どこでそれを取得するために何か賢いことをしていますか? もう1つのこと(質問に入れるのを忘れていました)は、キャストを削除したときに警告が最初に消えたと思いましたint。私はそれを再現することはできませんが、それには別の説明があるに違いないと思います. おそらく、誤ってまたは何か-std=c99からを削除したのでしょう。makefile

「標準 C では定義されていません」と言いました。そうではありませんが、POSIXにはあります。したがって、正しいヘッダー ( <stdlib.h>) を含め、宣言が表示されるようにすることで、関数は C ライブラリ (純粋な標準 C ライブラリではなく、多くの POSIX 関数も含まれています) から取得されます。および GLIBC に固有の他の多くの関数)。したがって、ライブラリに関数が含まれているため、機能します。の下で可視の宣言を取得するには、(システムヘッダーを含める前に)コンパイル-std=gnu99または指定する#define _XOPEN_SOURCE 700か、または同様のものを使用する必要がある場合があります。ヘッダーを使用して情報をプログラムに取り込みます。#define _POSIX_C_SOURCE 200809Lrandom()-std=c99posixver.h

/*
@(#)File:           $RCSfile: posixver.h,v $
@(#)Version:        $Revision: 1.1 $
@(#)Last changed:   $Date: 2010/08/29 00:27:48 $
@(#)Purpose:        Request appropriate POSIX and X/Open Support
@(#)Author:         J Leffler
*/

#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H

/*
** Include this file before including system headers.  By default, with
** C99 support from the compiler, it requests POSIX 2001 support.  With
** C89 support only, it requests POSIX 1997 support.  Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/

/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */

#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600   /* SUS v3, POSIX 1003.1 2004 (POSIX 2001 + Corrigenda) */
#else
#define _XOPEN_SOURCE 500   /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */

#endif /* JLSS_ID_POSIXVER_H */

これはかなり保守的で、POSIX 2008 のサポートを要求していません。なぜなら、私が使用している一部のマシンでは、POSIX 2008 のサポートが利用できないからです。必要に応じて、よりアグレッシブなバージョンのベースとして使用できます。以前はスタンザをプログラムに直接入れていましたが、POSIX 2008 に安全に変更できるようになると、これを修正するのは悪夢になります (そして、多くのソース ファイルでコメントを適切に維持することは、単純にばかげたことでした。そのため、ファイルには通常#define _XOPEN_SOURCE 600、.コメントは最小限またはまったくありませんが、変更するときに変更するのはまだ面倒です)。

于 2012-10-11T15:52:02.113 に答える