0

私のCファイルはclock_gettime(). これが機能するためには、man ページに従って、 が 含まれて<time.h>おり、 に定義_POSIX_C_SOURCEされています。(200112L)

SYNOPSIS
       #include <time.h>

       int clock_getres(clockid_t clk_id, struct timespec *res);

       int clock_gettime(clockid_t clk_id, struct timespec *tp);

       int clock_settime(clockid_t clk_id, const struct timespec *tp);

       Link with -lrt (only for glibc versions before 2.17).

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       clock_getres(), clock_gettime(), clock_settime():
              _POSIX_C_SOURCE >= 199309L

次のオプションを使用してコンパイルおよびリンクします。

CFLAGS = -g -Wall -Wextra -Werror -O3 -std=c99 -include $(PROJ_SETTINGS_INC) -lrt

、およびPROJ_SETTINGS_INC設定を含む h ファイルに設定されます。

これまでのところ、問題ありません。

ここで、設定ファイルを変更して を使用するuint16_tので<stdint.h>、設定 h ファイルに含めます。

clock_gettime()コンパイラは、それが暗黙の宣言であると不平を言うようになりました。

設定ファイルをintの代わりに使用するように戻し、uint16_tインクルードを に削除すると<stdint.h>、コンパイルが再び機能します。

<stdint.h>設定に h ファイルを含めると、なぜでのコンパイルが中断されるのclock_gettime()ですか?

私の最善の推測は、stdint定義を再定義することですが、ソースの最初の行でインクルードが行われたかのようにディレクティブが機能POSIXするため、意味がありません。-include


ここに例があります(ジョン・ボリンジャーの答えに照らして、何がうまくいかないのか理解し始めましたが、とにかくこれを書くと思いました)。

bar.h:

#include <stdint.h>

struct s {
    uint16_t a;
};

foo.c

#define _POSIX_C_SOURCE (199309L)

#include <stdio.h>
#include <time.h>

int main(void)
{
    struct s s;
    struct timespec now;

    s.a = 42;
    clock_gettime(CLOCK_REALTIME, &now);

    printf("answer: %d, time: %lld\n", s.a, (long long) now.tv_sec);

    return 0;
}

ビルド:

gcc foo.c -include bar.h

奇妙なことに、これは有用な警告を与えます。私の元のアプリケーションでは、暗黙の宣言エラーのみが発生しました。

foo.c:1:0: warning: "_POSIX_C_SOURCE" redefined [enabled by default]
 #define _POSIX_C_SOURCE (199309L)
 ^
In file included from /usr/include/stdint.h:25:0,
                 from /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdint.h:9,
                 from ./bar.h:1,
                 from <command-line>:1:
/usr/include/features.h:230:0: note: this is the location of the previous definition
 # define _POSIX_C_SOURCE 200809L
4

1 に答える 1

1

rici が指摘したように、POSIX では、指定された機能テスト マクロの (再) 定義が、他のヘッダー ファイルを含め、指定されたヘッダーのインクルードよりも前に行われる必要があります。そうしないと、動作は未定義です。マクロはその_POSIX_C_SOURCEような機能テスト マクロでありstdint.htime.h両方ともそのようなヘッダーです。

あなたの特定のケースでは、GNU Cライブラリのstdint.hヘッダーと他の多くは、どの機能が明示的に有効になっているかをチェックし、すべての機能マクロを一貫した値に設定する共通の内部ヘッダー( )に依存してfeatures.hいます(可能な限り)。マクロの値をチェックし、_POSIX_C_SOURCEまだ設定されていない場合は設定します。複数回処理されるのを避けるために、標準のガード マクロを使用します。したがって、フィーチャー マクロが後で再定義されると、フィーチャー定義の一貫性が失われる危険性があります。

特定のケースで宣言に失敗する原因となる定義と再定義の正確なチェーンを追跡していませんclock_gettime()(実際、そうするのに十分な情報を提供していません)が、機能マクロを定義する場合は、すべてのヘッダーにこれらの定義が表示されるようにする必要があります。これらは#includeディレクティブの前にソース ファイルに表示する必要があります。そうしないと、システム ヘッダーがそれらの定義の前に前処理されることを避ける必要があります (たとえば、-includeオプションで指定されたファイル内のディレクティブを介して)。

また、実装の詳細について議論していますが、GNU の実装がこの点で異常であると考える理由はないことにも注意してください。他のものは多少異なる方法で実装されますが、すべてのヘッダーが、それらに影響を与えるマクロの定義の一貫したセットを参照できるようにすることが常に賢明です。POSIXで規定されていないマクロでも。

于 2015-02-17T16:36:23.763 に答える