【问题标题】:Why does clock_gettime not compile when using C99?为什么使用 C99 时clock_gettime 无法编译?
【发布时间】:2021-11-07 18:11:47
【问题描述】:

为什么这段 C 代码在 C99 中编译?我应该阅读什么来了解更多信息?

除非我添加更多文字,否则我无法发布,所以这里有一些废话,因为我认为没有其他要说的了

$ 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.

【问题讨论】:

  • 这个答案吗? stackoverflow.com/questions/3875197/… c11 有,其他一些东西(posix)也有。只是c99没有。如果使用 c99,则启用其他东西
  • clock_gettime 不是 C99 的一部分,代码可以使用 GNU99 扩展 -std=gnu99#define _POSIX_C_SOURCE 200112L 宏进行编译
  • “在 C99 中无效”是因为在未启用 POSIX 功能测试宏的情况下,&lt;time.h&gt; 不包含clock_gettime 的声明。在 C99 之前,即使没有声明,使用函数也是合法的(尽管通常是错误的);编译器假定函数的隐式声明返回int 并采用未指定的参数。在 C99 中,这是未定义的行为,但 GCC 在发出警告后仍会提供较旧的行为。无论如何,您不想要任何这些;正确的解决方法是定义功能测试宏并从&lt;time.h&gt; 获取正确的声明。

标签: c99 libc system-clock


【解决方案1】:

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

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

引用feature_test_macros(7):

__STRICT_ANSI__

ISO 标准 C。当使用 -std=c99-ansi 标志调用时,此宏由 gcc(1) 隐式定义。

[…]

如果__STRICT_ANSI___ISOC99_SOURCE_ISOC11_SOURCE(自 glibc 2.18 起)、_POSIX_SOURCE_POSIX_C_SOURCE_XOPEN_SOURCE_XOPEN_SOURCE_EXTENDED(在 glibc 2.11 及更早版本中)、_BSD_SOURCE 中的任何一个在 glibc 2.19 及更早版本中)或 _SVID_SOURCE(在 glibc 2.19 及更早版本中)显式定义,则默认未定义 _BSD_SOURCE_SVID_SOURCE_DEFAULT_SOURCE

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

【讨论】:

    猜你喜欢
    • 2012-10-15
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 2016-08-30
    • 2015-01-12
    • 2011-02-25
    相关资源
    最近更新 更多