为什么使用C99时clock_gettime编译不通过?

Why does clock_gettime not compile when using C99?

为什么这个C代码在C99中编译?我应该阅读哪些内容以了解更多信息?

我不能post除非我添加更多的文字所以这里有一些废话因为我认为没有什么可以说的

$ cat m.c
#include <stdio.h>
#include <time.h>
int main() {
    struct timespec time;
    int res = clock_gettime(CLOCK_REALTIME, &time);
    printf("%d %ld %ld\n", res, time.tv_sec, time.tv_nsec);
    return 0;
}


$ clang m.c && ./a.out && rm ./a.out
0 1631386905 774654955


$ clang -std=c99 m.c && ./a.out && rm ./a.out
m.c:4:18: error: variable has incomplete type 'struct timespec'
        struct timespec time;
                        ^
m.c:4:9: note: forward declaration of 'struct timespec'
        struct timespec time;
            ^
m.c:5:12: warning: implicit declaration of function 'clock_gettime' is invalid in C99 [-Wimplicit-function-declaration]
        int res = clock_gettime(CLOCK_REALTIME, &time);
                ^
m.c:5:26: error: use of undeclared identifier 'CLOCK_REALTIME'
        int res = clock_gettime(CLOCK_REALTIME, &time);
                                ^
1 warning and 2 errors generated.

因为使用-std=c99选项定义了一个宏,导致clock_gettime的声明被隐藏

GNU C 库可以公开其函数的不同版本,或完全隐藏它们,具体取决于用户代码的期望。用户代码通过定义某些具有 GNU C 识别的 pre-determined 值的 specially-named 宏(称为 功能测试宏 ,尽管这是用词不当)来声明这些期望图书馆 headers。一个这样的宏是 __STRICT_ANSI__,如果使用任何 -std=c<i>XX</i> 选项,它就会被隐式定义。

引用 feature_test_macros(7):

__STRICT_ANSI__

ISO Standard C. This macro is implicitly defined by gcc(1) when invoked with, for example, the -std=c99 or -ansi flag.

[…]

If any of __STRICT_ANSI__, _ISOC99_SOURCE, _ISOC11_SOURCE (since glibc 2.18), _POSIX_SOURCE, _POSIX_C_SOURCE, _XOPEN_SOURCE, _XOPEN_SOURCE_EXTENDED (in glibc 2.11 and earlier), _BSD_SOURCE (in glibc 2.19 and earlier), or _SVID_SOURCE (in glibc 2.19 and earlier) is explicitly defined, then _BSD_SOURCE, _SVID_SOURCE, and _DEFAULT_SOURCE are not defined by default.

使用 -std=gnu<i>XX</i> 选项而不是 -std=c<i>XX</i> 不会导致定义 __STRICT_ANSI__;它还支持对 C 语言的 GNU 扩展。如果你想禁用这些语言扩展,你可以将 #define _DEFAULT_SOURCE 1 放在文件的最顶部以暴露 C 库否则会暴露的所有符号(或者可能是另一个功能测试宏来调整库接口你喜欢的)。显式功能测试宏将优先于 __STRICT_ANSI__.