web-dev-qa-db-ja.com

関数usleepの暗黙的な宣言

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

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

23
ant2009

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

ヘッダーファイル自体は、通常#ifdefステートメントの大規模なネスト内にあるusleepのみを定義し、開発者は、あなたがする必要がないことをあなたに伝えるために時間をかけましたあなた自身でそれを理解しようと何時間も費やします:-)

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

  • _BSD_SOURCEを宣言します。または
  • 他の3つの事柄の複雑な組み合わせを宣言しますが、これをデコードすることはありません。

おそらく最も簡単な解決策は、単にgcc -D _BSD_SOURCEでコンパイルするか、

#define _BSD_SOURCE

usleepを提供するヘッダーファイルをインクルードする前のコードで。

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

28
paxdiablo

これは動作する可能性があります:Linuxでgccを使用してコンパイルする場合、-std=gnu99を追加します。

例:

arm-linux-gcc -lpthread -std=gnu99  -o test ArmLinuxDataPipe1.2.1.c
19
ioilala

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_SOURCEおよびman 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 SUSは、POSIXのスーパーセットであり、通常は何を記述しますか。以前は、次のバージョンを有効にするために宣言できるさまざまな機能テストマクロがありました。これらの標準は、下位互換性のために引き続きサポートされています。貼り付けた条件でそれらの一部を確認できますが、新しいコードを記述するときにそれらを心配する必要はありません。コードをチェックするマクロは、_XOPEN_SOURCE_EXTENDEDです。時代遅れですが、歴史的に1995年からSUSのバージョンを選択しました。

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

したがって、これらの条件が意味するのは、usleep()はPOSIX関数ではなく、一部のBSD系OSに一度存在したため、SUS 1995年に廃止されました。2008年に廃止され、POSIXの任意のバージョンまたはSUSを選択すると、それがアクティブに無効になります。したがって、SUS(および他の古い同義語もオンにします)、しかし、POSIXまたはSUSの最新バージョンを選択した場合は非推奨です。anything-goesオプションを選択した場合も有効になりますが、それは悪いことです考え。

2
Davislor

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

_// 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 / 1e6;             // whole seconds
    ts.tv_nsec = (microseconds % 1e6) * 1e3;    // 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
1
Gabriel Staples

代わりにnanosleep()を使用するとうまくいきました。

関連する注意事項:usleep()はPOSIX-2008から削除され、代わりにnanosleep()を使用することを推奨しています。

1
electron1979