为什么 GCC 声称 clock_gettime() 隐式声明,但预处理器对相关宏非常满意?

Why does GCC claim clock_gettime() implicitly declared, but the preprocessor is perfectly happy with a related macro?

我正在尝试尽可能准确地测量操作所花费的时间。我的研究让我相信 clock_gettime() 和朋友是我想要的。

但是,我一辈子都无法让它工作。考虑这个看似微不足道的例子:

#include <time.h>
#include <unistd.h>

int main(void)
{
    struct timespec t;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t);
    return 0;
}

如果我 运行 通过预处理器,一切看起来都很好:

$ cpp time.c | tail -n10
# 1163 "/usr/include/unistd.h" 3 4

# 3 "time.c" 2

int main(void)
{
 struct timespec t;
 clock_gettime(2, &t);
 return 0;
}

但是,如果我尝试编译预处理代码,它不会:

$ cpp time.c > time-prep.c
$ cc -o time -Wall -std=c11 -lrt time-prep.c
/tmp/user/1000/cc00SdhB.o: In function `main':
time-prep.c:(.text+0x15): undefined reference to `clock_gettime'
collect2: error: ld returned 1 exit status
$ 

如果我尝试编译原始版本,它并没有变得更好:

$ cc -o time -Wall -std=c11 -lrt time.c
time.c: In function ‘main’:
time.c:6:18: error: storage size of ‘t’ isn’t known
time.c:7:2: warning: implicit declaration of function ‘clock_gettime’ [-Wimplicit-function-declaration]
time.c:7:16: error: ‘CLOCK_PROCESS_CPUTIME_ID’ undeclared (first use in this function)
time.c:7:16: note: each undeclared identifier is reported only once for each function it appears in
time.c:6:18: warning: unused variable ‘t’ [-Wunused-variable]
$ 

clock_gettime 的手册页说我需要

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

但如您所见,我已经在这样做了。在我的情况下,将 -lrt 添加或删除到 cc 似乎没有任何区别。

我查看了 /usr/include/time.h,但没有发现任何明显的遗漏。

为了能够在我的代码中使用 clock_gettime(),我缺少什么(大概是微不足道的)咒语?

clock_gettime() 的 Linux 文档指定了功能测试要求:

_POSIX_C_SOURCE >= 199309L

您可以考虑直接实现它,或许可以通过代码最开头的 #define 指令,因为代码实际上确实依赖于它。

如果您不提供这样的 #define,那么 gcc 仍然可以为您提供,具体取决于您为其指定的选项。默认情况下,它会做。 -std=gnu99-std=gnu11 也是如此。但是您尝试使用 -std=c11 进行编译,这要求严格(大概)遵守 C11。 C11 未定义所需的 POSIX 功能测试宏。

您可以在_GNU_SOURCE 上方定义任何#include。有一个例子:

$cat ./main.c

// Need for clock_gettime()
// Have to be at the begining of the file
#define _GNU_SOURCE

#include <time.h>
#include <unistd.h>

int main(void)
{
    ...
}