31
gcc (GCC) 4.6.3
c89

を使おうとしていますusleep。ただし、次の警告が引き続き表示されます。

関数 usleep の暗黙の宣言

unistd.hヘッダーファイルを含めました。

マニュアルページには、これについて何か言及されています。しかし、それで理解しているかどうかはわかりません:

usleep():
   Since glibc 2.12:
       _BSD_SOURCE ||
           (_XOPEN_SOURCE >= 500 ||
               _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) &&
           !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
   Before glibc 2.12:
       _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED

しかし、私が上記で何をすべきかわからないのですか?

4

6 に答える 6

35

そのリストは、usleep定義済みの前提条件です。#defineこれは基本的に、ヘッダー ファイルをインクルードする前に真でなければならない変数を含む C に似た式です。

usleepヘッダー ファイル自体は、通常は大量のステートメントのネストである内部のみを定義#ifdefし、開発者は何をする必要があるかを説明するために時間をかけたので、自分でそれを理解するのに何時間も費やす必要はありません :-)

2.12 以降を使用していると仮定すると、次のglibcいずれかを行う必要があります。

  • _BSD_SOURCE を宣言します。また
  • 他の 3 つのものの複雑な組み合わせを宣言しますが、これについてはあえて解読しません。

おそらく最も簡単な修正は、単純にコンパイルするgcc -D _BSD_SOURCEか、以下を配置することです。

#define _BSD_SOURCE

を提供するヘッダー ファイルをインクルードする前に、コードにusleep.

さまざまなヘッダー ファイル間に依存関係がある場合に備えてインクルードの前にこれらを定義することをお勧めします。

于 2012-04-07T10:49:50.717 に答える
5

Tl;dr

コンパイルに使用するレガシー コードを取得する必要がusleep()ある場合は、他のライブラリよりも前にインクルードするヘッダー ファイルに次の行を追加します。

#define _XOPEN_SOURCE   600
#define _POSIX_C_SOURCE 200112L

または、コンパイラ フラグ-std=c11 -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112Lをメイクファイルに追加します。

これは、非推奨ではなかったこの古いバージョンの UNIX API をプログラムが使用していることを環境に伝えます。usleep()

または、これが新しいコードである場合は間違いなく、 に置き換え、ライブラリのバージョンに合わせて機能テスト マクロを適切に設定usleep()nanosleep()、コードベースを見直して他のビット腐敗を調べます。

Linux では、ライブラリがサポートする_XOPEN_SOURCEとの値を で確認できます。_POSIX_C_SOURCEman feature_test_macros

全体像

より長い答え: これが何が起こっているかです。

歴史的にいくつかの異なる UNIX 標準があり、最終的に誰もが思いついたベスト プラクティスは、コードがどのバージョンの UNIX API 用に記述されているかをコードに指定することでした。プログラマーは、機能テスト マクロを定義することでこれを行いました。

UNIX における初期の分割の 1 つは、AT&T の System V とカリフォルニア大学の Berkeley Standard Distribution (BSD) の間でした。System V が公式バージョンであり、その動作がデフォルトになったのに対し、BSD Unix は初期のフリー ソフトウェアの一部であり、多くの大学で使用されていたため_BSD_SOURCE_SVID_SOURCE. この_BSD_SOURCEマクロは特に、40 年以上にわたってさまざまなオペレーティング システムの拡張機能を有効にしようとしています。非標準の拡張機能のキャッチオールとして使用されることもあります。両方のマクロは非推奨であり、現在受け入れられている回答に反して、新しいコードではどちらも使用しないでください。

今世紀には、IEEE 標準となった POSIX と、Open Group (X/Open) の Single Unix Specification (SUS) という 2 つの UNIX 標準がありました。X/Open SU​​S は POSIX のスーパーセットであり、通常はその目的で作成されます。以前は、これらの標準の当時の最新バージョンを有効にするために宣言できるさまざまな機能テスト マクロが多数ありましたが、これらは下位互換性のために引き続きサポートされています。貼り付けた条件にいくつか表示されますが、新しいコードを記述するときに気にする必要はありません。コードをチェックする 1 つのマクロ_XOPEN_SOURCE_EXTENDEDは現在は廃止されていますが、歴史的には 1995 年から SUS のバージョンが選択されていました。

理論的には、最新バージョンの UNIX または Linux で設定する正しい機能テスト マクロは_XOPEN_SOURCE. ライブラリがサポートする最新のバージョン番号を調べる必要があります。実際には、他の誰もそれを矛盾して設定してコードを壊すことができないことを保証_POSIX_C_SOURCEするために、も定義するのが賢明な防御コーディングだと思います。あなたの質問は良い例です。下位互換性を設定しても、ツールチェーンの他の場所でより新しいバージョンに設定されている場合、より高いバージョンのが優先され、機能しません。_XOPEN_SOURCE_POSIX_C_SOURCE_POSIX_C_SOURCEusleep()

したがって、これらの条件が意味するのは、usleep()これは POSIX 関数ではなく、BSD ライクな OS に一時的に存在していたため、1995 年に SUS に組み込まれたことです。2008 年に廃止され、POSIX またはそれ以来、SUS はそれを積極的に無効にします。したがって、SUS のバージョン 500 または 600 を選択すると有効になります (また、もう 1 つの廃止されたシノニムも有効にします) が、POSIX または SUS の最近のバージョンを選択すると非推奨になります。何でもありのオプションを選択した場合にも有効になりますが、それは悪い考えです.

于 2019-04-26T04:33:31.103 に答える
3

コードの先頭に次を追加します。

// For `nanosleep()`:
#include <time.h>

#define __USE_POSIX199309
#define _POSIX_C_SOURCE 199309L

そして、nanosleep()代わりに使用しsleep_us()て、設定されたマイクロ秒数だけスリープする独自の関数を作成します。

void sleep_us(unsigned long microseconds)
{
    struct timespec ts;
    ts.tv_sec = microseconds / 1000000ul;            // whole seconds
    ts.tv_nsec = (microseconds % 1000000ul) * 1000;  // remainder, in nanoseconds
    nanosleep(&ts, NULL);
}

Linux Ubuntu でコンパイルして実行するために、sleep_test.cファイルを作成し、以下を使用しました。

gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_test

参考文献:

  1. (これは意図的に循環参照です。この回答の下にある私のコメントを参照してください): C にミリ秒単位の別のスリープ機能はありますか?
  2. http://man7.org/linux/man-pages/man2/nanosleep.2.html
于 2019-04-26T03:00:28.350 に答える