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

a C*_*CVn 4 c time gcc glibc

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

\n\n

然而,我一生都无法让它发挥作用。考虑这个看似微不足道的例子:

\n\n
#include <time.h>\n#include <unistd.h>\n\nint main(void)\n{\n    struct timespec t;\n    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t);\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
$ cpp time.c | tail -n10\n# 1163 "/usr/include/unistd.h" 3 4\n\n# 3 "time.c" 2\n\nint main(void)\n{\n struct timespec t;\n clock_gettime(2, &t);\n return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

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

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

\n\n
$ cc -o time -Wall -std=c11 -lrt time.c\ntime.c: In function \xe2\x80\x98main\xe2\x80\x99:\ntime.c:6:18: error: storage size of \xe2\x80\x98t\xe2\x80\x99 isn\xe2\x80\x99t known\ntime.c:7:2: warning: implicit declaration of function \xe2\x80\x98clock_gettime\xe2\x80\x99 [-Wimplicit-function-declaration]\ntime.c:7:16: error: \xe2\x80\x98CLOCK_PROCESS_CPUTIME_ID\xe2\x80\x99 undeclared (first use in this function)\ntime.c:7:16: note: each undeclared identifier is reported only once for each function it appears in\ntime.c:6:18: warning: unused variable \xe2\x80\x98t\xe2\x80\x99 [-Wunused-variable]\n$ \n
Run Code Online (Sandbox Code Playgroud)\n\n

Clock_gettime 的手册页说我需要

\n\n
\n

链接-lrt(仅适用于 2.17 之前的 glibc 版本)。

\n
\n\n

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

\n\n

我已经看过了/usr/include/time.h,但没有看到任何明显的我遗漏的东西。

\n\n

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

\n

Joh*_*ger 5

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

_POSIX_C_SOURCE >= 199309L
Run Code Online (Sandbox Code Playgroud)

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

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