简体   繁体   English

带有 -std=c99 的 GCC 抱怨不知道 struct timespec

[英]GCC with -std=c99 complains about not knowing struct timespec

When I try to compile this on Linux with gcc -std=c99 , the compiler complains about not knowing struct timespec .当我尝试在 Linux 上使用gcc -std=c99编译它时,编译器抱怨不知道struct timespec However if I compile this without -std=c99 everything works fine.但是,如果我在没有-std=c99情况下编译它,一切正常。

#include <time.h>

int main(void)
{
  struct timespec asdf;
  return 0;
}

Why is this and is there a way to still get it to work with -std=c99 ?为什么会这样,有没有办法让它与-std=c99一起工作?

Explicitly enabling POSIX features显式启用 POSIX 功能

The timespec comes from POSIX, so you have to 'enable' POSIX definitions: timespec 来自 POSIX,因此您必须“启用”POSIX 定义:

#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif /* __STDC_VERSION__ */

#include <time.h>

void blah(struct timespec asdf)
{
}

int main()
{
    struct timespec asdf;
    return 0;
}

The stanza at the top is what I currently use - it triggers the definitions from Single UNIX Specification (SUS) based on whether you're using a C99 or C89 compiler.顶部的节是我目前使用的 - 它根据您使用的是 C99 还是 C89 编译器触发来自单一 UNIX 规范 (SUS) 的定义。

  • If you want the POSIX 2008 (SUS v4) material, use _XOPEN_SOURCE 700如果您想要POSIX 2008 (SUS v4) 材料,请使用_XOPEN_SOURCE 700
  • If you want the POSIX 2004 (SUS v3) material, use _XOPEN_SOURCE 600如果您需要POSIX 2004 (SUS v3) 材料,请使用_XOPEN_SOURCE 600
  • If you want the POSIX 1995 (SUS v2, 1997) material, use _XOPEN_SOURCE 500如果您需要POSIX 1995 (SUS v2, 1997) 材料,请使用_XOPEN_SOURCE 500

As noted in the comments, using _XOPEN_SOURCE strictly enables the XSI (X/Open System Interface) extensions over strict POSIX, but it is very rare for you to want POSIX and not XSI.如评论中所述,使用_XOPEN_SOURCE严格启用 XSI(X/开放系统接口)扩展而不是严格的 POSIX,但您想要 POSIX 而不是 XSI 的情况非常少见。 You should normally specify _XOPEN_SOURCE and not futz with _POSIX_C_SOURCE .您通常应该指定_XOPEN_SOURCE而不是_POSIX_C_SOURCE See (POSIX 2018) on The Compilation Environment for more information about feature macros.有关功能宏的更多信息,请参阅编译环境(POSIX 2018)。

For my systems in 2010, POSIX 2008 was not as widely available as POSIX 2004, so that's what I used - but YMMV.对于我 2010 年的系统,POSIX 2008 不像 POSIX 2004 那样广泛可用,所以这就是我使用的 - 但 YMMV。 Note that SUS v3 and v4 both require C99 compilation.请注意,SUS v3 和 v4 都需要 C99 编译。 On Solaris, at least, using C89 failed.至少在 Solaris 上,使用 C89 失败了。

GCC provides -std=gnuXX options GCC 提供-std=gnuXX选项

If you specify -std=c11 to GCC (or Clang emulating GCC), then only the standard C definitions are enabled.如果您为 GCC(或 Clang 模拟 GCC)指定-std=c11 ,则仅启用标准 C 定义。 If you use -std=gnu11 , then POSIX and other extensions to standard C are visible by default.如果您使用-std=gnu11 ,则默认情况下可以看到 POSIX 和标准 C 的其他扩展。

Note that GCC 4.x and earlier used -std=gnu90 (corresponding to C90 plus extensions) by default.请注意,GCC 4.x 及更早版本默认使用-std=gnu90 (对应于 C90 加扩展)。 GCC 5.x and later use -std=gnu11 by default. GCC 5.x 及更高版本默认使用-std=gnu11 There was never a version of GCC that enabled -std=gnu99 by default.默认情况下,从来没有启用-std=gnu99的 GCC 版本。

Use a header to control the POSIX version information使用标头控制 POSIX 版本信息

I now (2019) use a header to encapsulate this information so that future changes only require the change to a single header, not to every source file that uses POSIX features.我现在(2019 年)使用标头来封装此信息,以便将来的更改只需要更改单个标头,而不是每个使用 POSIX 功能的源文件。 It was painful editing the old stanza out of multiple source files as time passed and POSIX 2008 became prevalent.随着时间的推移和 POSIX 2008 的流行,从多个源文件中编辑旧的节是一件痛苦的事情。

/*
@(#)File:           $RCSfile: posixver.h,v $
@(#)Version:        $Revision: 1.4 $
@(#)Last changed:   $Date: 2017/06/18 00:15:42 $
@(#)Purpose:        Request appropriate POSIX and X/Open Support
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 2010-2017
*/

/*TABSTOP=4*/

#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H

/*
** Include this file before including system headers.  By default, with
** C99 support from the compiler, it requests POSIX 2008 support.  With
** C89 support only, it requests POSIX 1997 support.  Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/

/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */

#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if defined(__cplusplus)
#define _XOPEN_SOURCE 700   /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */
#elif __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 700   /* SUS v4, POSIX 1003.1 2008/13 (POSIX 2008/13) */
#else
#define _XOPEN_SOURCE 500   /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */

#endif /* JLSS_ID_POSIXVER_H */

You may use the information from this header without the attribution and copyright notice normally required by the "CC by-sa 3.0" licence used by Stack Overflow.您可以使用此标题中的信息,而无需 Stack Overflow 使用的“CC by-sa 3.0”许可通常要求的归属和版权声明。 This code is available in my SOQ (Stack Overflow Questions) repository on GitHub as file posixver.h in the src/libsoq sub-directory.此代码是我提供SOQ (堆栈溢出问题)在GitHub存储库中的文件posixver.hSRC / libsoq子目录。

C11 defines struct timespec C11 定义struct timespec

Note that C11 defines struct timespec , and does so in a way that is compatible with POSIX (which defined it first).请注意, C11定义了struct timespec ,并且以与 POSIX(首先定义它)兼容的方式进行定义。

The header <time.h> defines the type.标题<time.h>定义了类型。 Three of the functions that use it are declared in <threads.h> and the other is in <time.h> :使用它的三个函数在<threads.h>中声明,另一个在<time.h>

These are also part of C17 (C18) of course.当然,这些也是 C17 (C18) 的一部分。 You would have to be compiling with -std=c11 or similar (GCC 9.2.0 seems to recognize both -std=c17 and -std=c18 , and -std=c2x for the next version of the standard) for the type struct timespec to be defined automatically.您必须使用-std=c11或类似(GCC 9.2.0 似乎识别-std=c17-std=c18以及-std=c2x用于下一版本的标准)为类型struct timespec自动定义。

I would recommend compiling with -std=gnu99 .我建议使用-std=gnu99编译。

To elaborate on this.对此进行详细说明。 By default, gcc compiles with -std=gnu89.默认情况下,gcc 使用 -std=gnu89 进行编译。 Here are the results for the following source code.以下是以下源代码的结果。

#include <time.h>

int main() {
    struct timespec asdf;
    return 0;
}

[1:25pm][wlynch@cardiff /tmp] gcc -std=gnu89 foo.c
[1:26pm][wlynch@cardiff /tmp] gcc -std=gnu99 foo.c

[1:25pm][wlynch@cardiff /tmp] gcc -std=c89 foo.c
foo.c: In function ‘main’:
foo.c:4: error: storage size of ‘asdf’ isn’t known

[1:26pm][wlynch@cardiff /tmp] gcc -std=c99 foo.c
foo.c: In function ‘main’:
foo.c:4: error: storage size of ‘asdf’ isn’t known

Adding -D_GNU_SOURCE to your CFLAGS will also work.将 -D_GNU_SOURCE 添加到您的 CFLAGS 也将起作用。

gcc test.c -o test -std=c99 -D_GNU_SOURCE gcc test.c -o test -std=c99 -D_GNU_SOURCE

Have a look at /usr/include/time.h.看看/usr/include/time.h。 This is the preprocessor conditional that wraps the timespec definition.这是包装 timespec 定义的预处理器条件。 _GNU_SOURCE enables __USE_POSIX199309. _GNU_SOURCE 启用 __USE_POSIX199309。

#if (!defined __timespec_defined                    \
 && ((defined _TIME_H                       \
  && (defined __USE_POSIX199309                 \
      || defined __USE_ISOC11))                 \
 || defined __need_timespec))
 # define __timespec_defined 1                                                                                                                                                                                                                 
 struct timespec
 {
    __time_t tv_sec;        /* Seconds.  */
    __syscall_slong_t tv_nsec;  /* Nanoseconds.  */
 }; 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM