GCC с -std = c99 жалуется на то, что не знает struct timespec - PullRequest
40 голосов
/ 06 октября 2010

Когда я пытаюсь скомпилировать это в Linux с gcc -std=c99, компилятор жалуется, что не знает struct timespec. Однако, если я скомпилирую это без -std=c99, все будет нормально.

#include <time.h>

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

Почему это так и есть ли способ заставить его работать с -std=c99?

Ответы [ 2 ]

55 голосов
/ 06 октября 2010

Явное включение функций POSIX

Тайм-спек получен из 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;
}

Раздел в верхней части - это то, чем я сейчас пользуюсь - он запускает определения из Single UNIX Specification (SUS) в зависимости от того, используете ли вы компилятор C99 или C89.

  • Если вы хотите материал 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 / Open System Interface) поверх строгого POSIX, но очень редко вы предпочитаете POSIX, а не XSI. Обычно вы должны указать _XOPEN_SOURCE, а не futz с _POSIX_C_SOURCE. См. (POSIX 2018) на Среда компиляции для получения дополнительной информации о макросах функций.

Для моих систем в 2010 году POSIX 2008 был не так широко доступен, как POSIX 2004, поэтому я использовал его - но YMMV. Обратите внимание, что для SUS v3 и v4 требуется компиляция C99. По крайней мере, в Solaris использование C89 не удалось.

GCC предоставляет -std=gnuXX опции

Если вы укажете -std=c11 для GCC (или Clang, эмулирующим GCC), то будут включены только стандартные определения языка C. Если вы используете -std=gnu11, то по умолчанию видимы POSIX и другие расширения стандарта C.

Обратите внимание, что GCC 4.x и более ранние версии по умолчанию использовали -std=gnu90 (соответствует расширениям C90 plus). GCC 5.x и более поздние версии используют -std=gnu11 по умолчанию. Никогда не было версии GCC, которая бы включала -std=gnu99 по умолчанию.

Использование заголовка для управления информацией о версии 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 */

Вы можете использовать информацию из этого заголовка без указания авторства и авторских прав, обычно требуемых лицензией «CC by-sa 3.0», используемой Stack Overflow. Этот код доступен в моем репозитории SOQ (Вопросы о переполнении стека) на GitHub в виде файла posixver.h в подкаталоге src / libsoq .

41 голосов
/ 06 октября 2010

Я бы порекомендовал компилировать с -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
...