簡體   English   中英

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

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

當我嘗試在 Linux 上使用gcc -std=c99編譯它時,編譯器抱怨不知道struct timespec 但是,如果我在沒有-std=c99情況下編譯它,一切正常。

#include <time.h>

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

為什么會這樣,有沒有辦法讓它與-std=c99一起工作?

顯式啟用 POSIX 功能

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;
}

頂部的節是我目前使用的 - 它根據您使用的是 C99 還是 C89 編譯器觸發來自單一 UNIX 規范 (SUS) 的定義。

  • 如果您想要POSIX 2008 (SUS v4) 材料,請使用_XOPEN_SOURCE 700
  • 如果您需要POSIX 2004 (SUS v3) 材料,請使用_XOPEN_SOURCE 600
  • 如果您需要POSIX 1995 (SUS v2, 1997) 材料,請使用_XOPEN_SOURCE 500

如評論中所述,使用_XOPEN_SOURCE嚴格啟用 XSI(X/開放系統接口)擴展而不是嚴格的 POSIX,但您想要 POSIX 而不是 XSI 的情況非常少見。 您通常應該指定_XOPEN_SOURCE而不是_POSIX_C_SOURCE 有關功能宏的更多信息,請參閱編譯環境(POSIX 2018)。

對於我 2010 年的系統,POSIX 2008 不像 POSIX 2004 那樣廣泛可用,所以這就是我使用的 - 但 YMMV。 請注意,SUS v3 和 v4 都需要 C99 編譯。 至少在 Solaris 上,使用 C89 失敗了。

GCC 提供-std=gnuXX選項

如果您為 GCC(或 Clang 模擬 GCC)指定-std=c11 ,則僅啟用標准 C 定義。 如果您使用-std=gnu11 ,則默認情況下可以看到 POSIX 和標准 C 的其他擴展。

請注意,GCC 4.x 及更早版本默認使用-std=gnu90 (對應於 C90 加擴展)。 GCC 5.x 及更高版本默認使用-std=gnu11 默認情況下,從來沒有啟用-std=gnu99的 GCC 版本。

使用標頭控制 POSIX 版本信息

我現在(2019 年)使用標頭來封裝此信息,以便將來的更改只需要更改單個標頭,而不是每個使用 POSIX 功能的源文件。 隨着時間的推移和 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 */

您可以使用此標題中的信息,而無需 Stack Overflow 使用的“CC by-sa 3.0”許可通常要求的歸屬和版權聲明。 此代碼是我提供SOQ (堆棧溢出問題)在GitHub存儲庫中的文件posixver.hSRC / libsoq子目錄。

C11 定義struct timespec

請注意, C11定義了struct timespec ,並且以與 POSIX(首先定義它)兼容的方式進行定義。

標題<time.h>定義了類型。 使用它的三個函數在<threads.h>中聲明,另一個在<time.h>

當然,這些也是 C17 (C18) 的一部分。 您必須使用-std=c11或類似(GCC 9.2.0 似乎識別-std=c17-std=c18以及-std=c2x用於下一版本的標准)為類型struct timespec自動定義。

我建議使用-std=gnu99編譯。

對此進行詳細說明。 默認情況下,gcc 使用 -std=gnu89 進行編譯。 以下是以下源代碼的結果。

#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

將 -D_GNU_SOURCE 添加到您的 CFLAGS 也將起作用。

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

看看/usr/include/time.h。 這是包裝 timespec 定義的預處理器條件。 _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