Wenn ich versuche, diese unter Linux mit zu kompilieren gcc -std=c99
beschwert sich der Compiler darüber, es nicht zu wissen struct timespec
. Wenn ich dies jedoch ohne kompiliere -std=c99
alles funktioniert gut.
#include <time.h>
int main(void)
{
struct timespec asdf;
return 0;
}
Warum ist das so und gibt es eine Möglichkeit, es trotzdem zum Laufen zu bringen? -std=c99
?
Explizites Aktivieren von POSIX-Funktionen
Die Zeitangabe kommt von POSIX, also müssen Sie POSIX-Definitionen “aktivieren”:
#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;
}
Die Strophe ganz oben verwende ich derzeit – sie löst die Definitionen von Single UNIX Specification (SUS) aus, je nachdem, ob Sie einen C99- oder einen C89-Compiler verwenden.
- Wenn du willst POSIX 2008 (SUS v4)-Material verwenden
_XOPEN_SOURCE 700
- Wenn du willst POSIX 2004 (SUS v3)-Material verwenden
_XOPEN_SOURCE 600
- Wenn du willst POSIX 1995 (SUS v2, 1997) Material, verwenden
_XOPEN_SOURCE 500
Wie in den Kommentaren erwähnt, mit _XOPEN_SOURCE
aktiviert ausschließlich die XSI (X/Open System Interface)-Erweiterungen über striktes POSIX, aber es kommt sehr selten vor, dass Sie POSIX und nicht XSI wollen. Normalerweise sollten Sie angeben _XOPEN_SOURCE
und nicht mit futz _POSIX_C_SOURCE
. Siehe (POSIX 2018) auf Die Kompilierungsumgebung für weitere Informationen zu Funktionsmakros.
Für meine Systeme im Jahr 2010 war POSIX 2008 nicht so weit verbreitet wie POSIX 2004, also habe ich das verwendet – aber YMMV. Beachten Sie, dass SUS v3 und v4 beide eine C99-Kompilierung erfordern. Zumindest unter Solaris schlug die Verwendung von C89 fehl.
GCC bietet -std=gnuXX
Optionen
Wenn Sie angeben -std=c11
zu GCC (oder Clang, der GCC emuliert), dann sind nur die Standard-C-Definitionen aktiviert. Wenn du benutzt -std=gnu11
dann sind POSIX und andere Erweiterungen von Standard-C standardmäßig sichtbar.
Beachten Sie, dass GCC 4.x und früher verwendet werden -std=gnu90
(entspricht C90 plus Erweiterungen) standardmäßig. Verwendung von GCC 5.x und höher -std=gnu11
standardmäßig. Es gab nie eine Version von GCC, die aktiviert war -std=gnu99
standardmäßig.
Verwenden Sie einen Header, um die POSIX-Versionsinformationen zu steuern
Ich verwende jetzt (2019) einen Header, um diese Informationen zu kapseln, sodass zukünftige Änderungen nur die Änderung an einem einzigen Header erfordern, nicht an jeder Quelldatei, die POSIX-Funktionen verwendet. Es war schmerzhaft, die alte Strophe aus mehreren Quelldateien zu bearbeiten, als die Zeit verging und POSIX 2008 sich durchsetzte.
/*
@(#)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 */
Sie dürfen die Informationen aus diesem Header ohne die normalerweise von der von Stack Overflow verwendeten „CC by-sa 3.0“-Lizenz geforderten Zuordnungs- und Urheberrechtshinweise verwenden. Dieser Code ist in meiner verfügbar SOQ (Stack Overflow Questions) Repository auf GitHub als Datei posixver.h
in dem src/libsoq Unterverzeichnis.
C11 definiert struct timespec
Beachten Sie, dass C11 definiert struct timespec
und zwar auf eine Weise, die mit POSIX kompatibel ist (das es zuerst definiert hat).
Die Überschrift <time.h>
definiert den Typ. Drei der Funktionen, die es verwenden, sind in deklariert <threads.h>
und der andere ist drin <time.h>
:
Diese sind natürlich auch Teil von C17 (C18). Sie müssten mit kompilieren -std=c11
oder ähnlich (GCC 9.2.0 scheint beides zu erkennen -std=c17
und -std=c18
und -std=c2x
für die nächste Version der Norm) für den Typ struct timespec
automatisch zu definieren.
Ich würde empfehlen, mit zu kompilieren -std=gnu99
.
Um dies näher auszuführen. Standardmäßig wird gcc mit -std=gnu89 kompiliert. Hier sind die Ergebnisse für den folgenden Quellcode.
#include <time.h>
int main() {
struct timespec asdf;
return 0;
}
[1:25pm][[email protected] /tmp] gcc -std=gnu89 foo.c
[1:26pm][[email protected] /tmp] gcc -std=gnu99 foo.c
[1:25pm][[email protected] /tmp] gcc -std=c89 foo.c
foo.c: In function ‘main’:
foo.c:4: error: storage size of ‘asdf’ isn’t known
[1:26pm][[email protected] /tmp] gcc -std=c99 foo.c
foo.c: In function ‘main’:
foo.c:4: error: storage size of ‘asdf’ isn’t known
Das Hinzufügen von -D_GNU_SOURCE zu Ihren CFLAGS funktioniert auch.
gcc test.c -o test -std=c99 -D_GNU_SOURCE
Schauen Sie sich /usr/include/time.h an. Dies ist die Bedingung des Präprozessors, die die Zeitspezifikation umschließt. _GNU_SOURCE aktiviert __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. */
};