GCC mit -std=c99 beschwert sich darüber, dass er die Zeitangabe der Struktur nicht kennt

Lesezeit: 6 Minuten

Benutzeravatar von Nils
Nils

Wenn ich versuche, diese unter Linux mit zu kompilieren gcc -std=c99beschwert 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?

Benutzeravatar von Jonathan Leffler
Jonathan Leffler

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=gnu11dann 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 timespecund 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=c18und -std=c2x für die nächste Version der Norm) für den Typ struct timespec automatisch zu definieren.

  • Sie sollten definieren _POSIX_C_SOURCE auf die richtigen Werte, wenn Sie nur POSIX wollen. _XOPEN_SOURCE ist für XSI-Erweiterungen.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    6. Oktober 2010 um 18:42 Uhr

  • @R..: Ja, du hast pedantisch recht. Wollen Sie aber in der Praxis wirklich nur POSIX und nicht XSI? Wenn ja, können Sie einfach POSIX nachlesen und einstellen. Für die meisten Menschen ist die angegebene Lösung meistens sinnvoll.

    – Jonathan Leffler

    6. Oktober 2010 um 20:05 Uhr

  • Im neuesten SUS wurden so ziemlich alle lohnenden Funktionen auf die Basis verschoben, und XSI ist größtenteils Legacy-Schnittstellen-Cruft. Natürlich halte ich meinen Rücken frei, indem ich “meistens” sage. 😉

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    6. Oktober 2010 um 21:49 Uhr

  • _XOPEN_SOURCE bringt einige nützliche Sachen im Vergleich zu _POSIX_C_SOURCEzum Beispiel strdup(), strptime(), srandom(), realpath(), lockf() und einiges zur Unterstützung großer Dateien.

    – Mikel

    20. April 2011 um 0:22 Uhr


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][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

  • Nicht wirklich eine Antwort auf die Frage

    – Karel Petranek

    6. Oktober 2010 um 17:23 Uhr

  • Er vergleicht -std=gnu89 mit -std=c99. Der korrektere Vergleich wäre -std=gnu89 bis -std=gnu99. Obwohl ich zustimme, dass Jonathans Antwort viel besser erklärt, was hier vor sich geht.

    – Bill Lynch

    6. Oktober 2010 um 17:27 Uhr


  • Die Ablehnungen zu dieser Antwort sind völlig ungerechtfertigt. Es macht deutlich, dass das OP vergleicht gnu89 mit c99weshalb der Fehler auftritt, und zeigt, dass derselbe Fehler mit auftritt c89. Es handelt sich um nützliche Zusatzinformationen.

    – Café

    6. Oktober 2010 um 21:50 Uhr


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.  */
 }; 

1402610cookie-checkGCC mit -std=c99 beschwert sich darüber, dass er die Zeitangabe der Struktur nicht kennt

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy