Was ist time_t letztendlich ein Typedef?

Lesezeit: 10 Minuten

kals Benutzeravatar
Kal

Ich habe meine Linux-Box durchsucht und diese Typdefinition gesehen:

typedef __time_t time_t;

Aber ich konnte die nicht finden __time_t Definition.

Benutzeravatar von William Brendel
Wilhelm Brendel

Das time_t Wikipedia-Artikel Artikel bringt etwas Licht ins Dunkel. Die Quintessenz ist, dass die Art von time_t wird in der C-Spezifikation nicht garantiert.

Das time_t Datentyp ist ein Datentyp in der ISO-C-Bibliothek, der zum Speichern von Systemzeitwerten definiert ist. Solche Werte werden vom Standard zurückgegeben time()
Bibliotheksfunktion. Dieser Typ ist eine im Standardheader definierte Typedef. ISO C definiert time_t als arithmetischen Typ, spezifiziert aber keinen bestimmten Typ, Bereich, Auflösung oder Codierung dafür. Ebenfalls nicht spezifiziert sind die Bedeutungen von arithmetischen Operationen, die auf Zeitwerte angewendet werden.

Unix- und POSIX-kompatible Systeme implementieren die time_t tippe als ein signed
integer
(normalerweise 32 oder 64 Bit breit), die die Anzahl der Sekunden seit Beginn der Unix-Epoche darstellt
: Mitternacht UTC vom 1. Januar 1970 (ohne Schaltsekunden). Einige Systeme verarbeiten negative Zeitwerte korrekt, andere nicht. Systeme mit 32-Bit time_t Typ sind anfällig für die Jahr 2038 Problem.

  • Beachten Sie jedoch, dass time_t-Werte normalerweise nur im Arbeitsspeicher und nicht auf der Festplatte gespeichert werden. Stattdessen wird time_t zur dauerhaften Speicherung in Text oder ein anderes portables Format konvertiert. Das macht das Y2038-Problem nicht wirklich zu einem Problem.

    Benutzer25148

    23. Januar 2009 um 19:21 Uhr

  • @Heath: Auf einem bestimmten System, auf dem dieselben Personen das Betriebssystem und die C-Bibliothek erstellen, verwenden time_t in der Datenstruktur auf der Festplatte kann passieren. Da Dateisysteme jedoch häufig von anderen Betriebssystemen gelesen werden, wäre es dumm, das Dateisystem auf der Grundlage solcher implementierungsabhängiger Typen zu definieren. Beispielsweise könnte dasselbe Dateisystem sowohl auf 32-Bit- als auch auf 64-Bit-Systemen verwendet werden, und time_t könnte die Größe ändern. Daher müssen Dateisysteme genauer definiert werden (“32-Bit-Ganzzahl mit Vorzeichen, die die Anzahl der Sekunden seit Beginn des Jahres 1970 in UTC angibt”) als nur als time_t.

    Benutzer25148

    22. Mai 2011 um 8:44 Uhr

  • Als Hinweis: Der verlinkte Wikipedia-Artikel wurde entfernt und leitet jetzt zur Liste von weiter time.h Inhalt. Dieser Artikel verlinkt auf cppreference.com, aber der zitierte Inhalt ist nirgendwo zu finden …

    – Michał Górny

    30. August 2012 um 21:06 Uhr

  • @MichałGórny: Behoben, solange Artikel nicht gelöscht werden, kann man sich immer den Verlauf ansehen, um die richtige Version zu finden.

    – Zeta

    13. März 2013 um 7:51 Uhr

  • -1; die aus Wikipedia zitierte Behauptung, dass POSIX dies garantiert time_t signiert ist, ist falsch. pubs.opengroup.org/onlinepubs/9699919799/basedefs/… schreibt vor, dass verschiedene Dinge ein “vorzeichenbehafteter Integer-Typ” oder ein “unsigned Integer-Typ” sein müssen, aber von time_t es sagt nur, dass es “soll ein ganzzahliger Typ sein”. Eine Umsetzung vornehmen kann time_t unsigniert und dennoch POSIX-konform sein.

    – Mark Amery

    6. April 2019 um 19:30 Uhr

[root]# cat time.c

#include <time.h>

int main(int argc, char** argv)
{
        time_t test;
        return 0;
}

[root]# gcc -E time.c | grep __time_t

typedef long int __time_t;

Es ist definiert in $INCDIR/bits/types.h durch:

# 131 "/usr/include/bits/types.h" 3 4
# 1 "/usr/include/bits/typesizes.h" 1 3 4
# 132 "/usr/include/bits/types.h" 2 3 4

  • Ich sehe beides typedef __int32_t __time_t; und typedef __time_t time_t; in einem FreeBSD freebsd-test 8.2-RELEASE-p2 FreeBSD 8.2-RELEASE-p2 #8: Sun Aug 7 18:23:48 UTC 2011 root@freebsd-test:/usr/obj/usr/src/sys/MYXEN i386. Ihre Ergebnisse werden unter Linux explizit so gesetzt (zumindest auf 2.6.32-5-xen-amd64 von Debian).

    – ssi

    10. Mai 2012 um 17:21 Uhr

  • @Viet auch mit einem Einzeiler möglich, ohne eine Datei zu erstellen: stackoverflow.com/a/36096104/895245

    – Ciro Santilli OurBigBook.com

    18. März 2016 um 23:48 Uhr

  • Warum grep for __time_t und nicht time_t um den zugrunde liegenden Typ zu finden time_t? Einen Schritt auslassen?

    – chux – Wiedereinsetzung von Monica

    24. August 2019 um 16:12 Uhr

  • @chux-ReinstateMonica – Das OP sagte, er habe die Typedef von time_t bis __time_t gefunden. Diese Antwort befasst sich nur mit der gestellten Frage, als was __time_t definiert ist. Aber ich stimme zu, dass Sie für einen generischen Fall (wo time_t möglicherweise nicht in __time_t typisiert ist) zuerst nach time_t suchen und dann möglicherweise erneut nach dem suchen müssen, was das zurückgibt

    – Michael Firth

    28. Mai 2020 um 9:10 Uhr

  • @MichaelFirth Fair genug. Ich erinnere mich an meine Besorgnis, als ob OP gefunden hätte typedef __time_t time_t;ist auch eine Untersuchung des umgebenden Codes erforderlich, um sicherzustellen, dass typedef tatsächlich verwendet wurde und nicht nur Teil einer bedingten Kompilierung. typedef long time_t; wurde vielleicht auch gefunden.

    – chux – Wiedereinsetzung von Monica

    28. Mai 2020 um 14:20 Uhr


Ciro Santilli Benutzeravatar von OurBigBook.com
Ciro Santilli OurBigBook.com

Normen

William Brendel hat Wikipedia zitiert, aber ich bevorzuge es aus dem Maul des Pferdes.

C99 N1256 Standardentwurf 7.23.1/3 “Komponenten der Zeit” sagt:

Die deklarierten Typen sind size_t (beschrieben in 7.17), clock_t und time_t, die arithmetische Typen sind, die Zeiten darstellen können

und 6.2.5/18 “Typen” sagt:

Integer- und Floating-Typen werden gemeinsam als arithmetische Typen bezeichnet.

POSIX 7 sys_types.h sagt:

[CX] time_t muss ein ganzzahliger Typ sein.

wo [CX] ist definiert als:

[CX] Erweiterung des ISO C-Standards.

Es ist eine Erweiterung, weil es eine stärkere Garantie gibt: Fließkommazahlen sind out.

gcc Einzeiler

Keine Notwendigkeit, eine Datei zu erstellen, wie von Quassnoi erwähnt:

echo | gcc -E -xc -include 'time.h' - | grep time_t

Unter Ubuntu 15.10 GCC 5.2 lauten die oberen beiden Zeilen:

typedef long int __time_t;
typedef __time_t time_t;

Befehlsaufschlüsselung mit einigen Zitaten aus man gcc:

  • -E: “Stopp nach der Vorverarbeitungsphase; führe den Compiler nicht richtig aus.”
  • -xc: C-Sprache angeben, da die Eingabe von stdin kommt, das keine Dateierweiterung hat.
  • -include file: “Datei verarbeiten, als ob “#include “Datei”” als erste Zeile der primären Quelldatei angezeigt würde.”
  • -: Eingabe von stdin

  • Auch die Pipe von Echo ist nicht erforderlich: gcc -E -xc -include time.h /dev/null | grep time_t

    – rvighne

    25. November 2019 um 18:58 Uhr

Benutzeravatar von pwrgreg007
pwrgreg007

Die Antwort ist definitiv implementierungsspezifisch. Um es definitiv für Ihre Plattform/Ihren Compiler herauszufinden, fügen Sie einfach diese Ausgabe irgendwo in Ihren Code ein:

printf ("sizeof time_t is: %d\n", sizeof(time_t));

Wenn die Antwort 4 (32 Bit) ist und Ihre Daten darüber hinausgehen sollen 2038dann haben Sie 25 Jahre Zeit, um Ihren Code zu migrieren.

Ihre Daten sind in Ordnung, wenn Sie Ihre Daten als Zeichenfolge speichern, auch wenn es sich um etwas Einfaches handelt wie:

FILE *stream = [stream file pointer that you've opened correctly];
fprintf (stream, "%d\n", (int)time_t);

Dann lesen Sie es einfach auf die gleiche Weise zurück (fread, fscanf usw. in ein int), und Sie haben Ihre Epochen-Offset-Zeit. Eine ähnliche Problemumgehung existiert in .Net. Ich übergebe problemlos 64-Bit-Epochennummern zwischen Win- und Linux-Systemen (über einen Kommunikationskanal). Das wirft Probleme mit der Byte-Reihenfolge auf, aber das ist ein anderes Thema.

Um die Frage von paxdiablo zu beantworten, würde ich sagen, dass es “19100” gedruckt hat, weil das Programm so geschrieben wurde (und ich gebe zu, dass ich das in den 80er Jahren selbst gemacht habe):

time_t now;
struct tm local_date_time;
now = time(NULL);
// convert, then copy internal object to our object
memcpy (&local_date_time, localtime(&now), sizeof(local_date_time));
printf ("Year is: 19%02d\n", local_date_time.tm_year);

Das printf -Anweisung gibt die feste Zeichenfolge “Jahr ist: 19” aus, gefolgt von einer mit Nullen aufgefüllten Zeichenfolge mit den “Jahren seit 1900” (Definition von tm->tm_year). Im Jahr 2000 liegt dieser Wert offensichtlich bei 100. "%02d" füllt mit zwei Nullen auf, schneidet aber nicht ab, wenn sie länger als zwei Ziffern sind.

Der richtige Weg ist (nur zur letzten Zeile wechseln):

printf ("Year is: %d\n", local_date_time.tm_year + 1900);

Neue Frage: Was ist der Grund für dieses Denken?

Unter Visual Studio 2008 ist es standardmäßig ein __int64 es sei denn, Sie definieren _USE_32BIT_TIME_T. Sie sind besser dran, wenn Sie einfach so tun, als wüssten Sie nicht, wie es definiert ist, da es sich von Plattform zu Plattform ändern kann (und wird).

  • Das funktioniert normalerweise, aber wenn Ihr Programm den Überblick über Dinge behalten soll, die in 30 Jahren passieren werden, ist es ziemlich wichtig, dass Sie es tun nicht haben eine vorzeichenbehaftete 32-Bit-time_t.

    – Rob Kennedy

    23. Januar 2009 um 0:35 Uhr

  • @Rob, bäh, lass es! Wir werden 2036 einfach anfangen, wie kopflose Hühner herumzurennen, genau wie im Jahr 2000. Einige von uns werden eine Menge Geld verdienen, indem sie Y2k38-Berater sind, Leonard Nimoy wird ein weiteres urkomisches Buch darüber herausbringen, wie wir uns alle im Wald verstecken sollten …

    – paxdiablo

    23. Januar 2009 um 0:40 Uhr

  • … und es wird alles vorbei sein, und die Öffentlichkeit fragt sich, worum es bei der ganzen Aufregung ging. Vielleicht komme ich sogar aus dem Ruhestand, um etwas Geld für das Erbe der Kinder zu verdienen :-).

    – paxdiablo

    23. Januar 2009 um 0:40 Uhr

  • Übrigens, wir haben nur einen Y2K-Fehler gefunden, und das war eine Webseite, die das Datum als 1. Januar 19100 auflistete. Übung für den Leser, warum …

    – paxdiablo

    23. Januar 2009 um 0:42 Uhr

  • Wenn das Ereignis, das in 30 Jahren eintreten wird, „Diese Sicherung ablaufen lassen“ lautet, dann könnten Sie JETZT in Schwierigkeiten sein, nicht im Jahr 2038. Addieren Sie 30 Jahre zur heutigen 32-Bit-Zeit_t hinzu, und Sie erhalten ein Datum in der Vergangenheit. Ihr Programm sucht nach zu verarbeitenden Ereignissen, findet eines, das überfällig ist (um 100 Jahre!), und führt es aus. Ups, kein Backup mehr.

    – Rob Kennedy

    23. Januar 2009 um 5:05 Uhr

Benutzeravatar von Sibren
Sibren

time_t ist vom Typ long int auf 64-Bit-Maschinen, sonst ist es long long int.

Sie können dies in diesen Header-Dateien überprüfen:

time.h: /usr/include
types.h und typesizes.h: /usr/include/x86_64-linux-gnu/bits

(Die folgenden Anweisungen stehen nicht hintereinander. Sie können in der jeweiligen Header-Datei mit Strg+f-Suche gefunden werden.)

1 in time.h

typedef __time_t time_t;

2)Ein types.h

# define __STD_TYPE     typedef  
__STD_TYPE __TIME_T_TYPE __time_t;  

3)Ein typesizes.h

#define __TIME_T_TYPE       __SYSCALL_SLONG_TYPE  
#if defined __x86_64__ && defined __ILP32__  
# define __SYSCALL_SLONG_TYPE   __SQUAD_TYPE  
#else
# define __SYSCALL_SLONG_TYPE   __SLONGWORD_TYPE
#endif  

4) Wieder rein types.h

#define __SLONGWORD_TYPE    long int
#if __WORDSIZE == 32
# define __SQUAD_TYPE       __quad_t
#elif __WORDSIZE == 64
# define __SQUAD_TYPE       long int  

#if __WORDSIZE == 64
typedef long int __quad_t;  
#else
__extension__ typedef long long int __quad_t;

  • Das funktioniert normalerweise, aber wenn Ihr Programm den Überblick über Dinge behalten soll, die in 30 Jahren passieren werden, ist es ziemlich wichtig, dass Sie es tun nicht haben eine vorzeichenbehaftete 32-Bit-time_t.

    – Rob Kennedy

    23. Januar 2009 um 0:35 Uhr

  • @Rob, bäh, lass es! Wir werden 2036 einfach anfangen, wie kopflose Hühner herumzurennen, genau wie im Jahr 2000. Einige von uns werden eine Menge Geld verdienen, indem sie Y2k38-Berater sind, Leonard Nimoy wird ein weiteres urkomisches Buch darüber herausbringen, wie wir uns alle im Wald verstecken sollten …

    – paxdiablo

    23. Januar 2009 um 0:40 Uhr

  • … und es wird alles vorbei sein, und die Öffentlichkeit fragt sich, worum es bei der ganzen Aufregung ging. Vielleicht komme ich sogar aus dem Ruhestand, um etwas Geld für das Erbe der Kinder zu verdienen :-).

    – paxdiablo

    23. Januar 2009 um 0:40 Uhr

  • Übrigens, wir haben nur einen Y2K-Fehler gefunden, und das war eine Webseite, die das Datum als 1. Januar 19100 auflistete. Übung für den Leser, warum …

    – paxdiablo

    23. Januar 2009 um 0:42 Uhr

  • Wenn das Ereignis, das in 30 Jahren eintreten wird, „Diese Sicherung ablaufen lassen“ lautet, dann könnten Sie JETZT in Schwierigkeiten sein, nicht im Jahr 2038. Addieren Sie 30 Jahre zur heutigen 32-Bit-Zeit_t hinzu, und Sie erhalten ein Datum in der Vergangenheit. Ihr Programm sucht nach zu verarbeitenden Ereignissen, findet eines, das überfällig ist (um 100 Jahre!), und führt es aus. Ups, kein Backup mehr.

    – Rob Kennedy

    23. Januar 2009 um 5:05 Uhr

Auf den meisten Legacy-Plattformen ist es ein 32-Bit-Ganzzahltyp mit Vorzeichen. Dies führt jedoch dazu, dass Ihr Code unter der leidet Jahr 2038 Fehler. Daher sollten moderne C-Bibliotheken es stattdessen als signiertes 64-Bit-Int definieren, das einige Milliarden Jahre lang sicher ist.

  • 2038 steht vor der Tür

    – Benutzer16217248

    6. August 2021 um 4:58 Uhr

1425960cookie-checkWas ist time_t letztendlich ein Typedef?

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

Privacy policy