¿Para qué es time_t, en última instancia, una definición de tipo?

Resuelto kal asked hace 15 años • 11 respuestas

Busqué en mi caja de Linux y vi este typedef:

typedef __time_t time_t;

Pero no pude encontrar la __time_t definición.

kal avatar Jan 23 '09 06:01 kal
Aceptado

El artículo time_t de Wikipedia arroja algo de luz sobre esto. La conclusión es que el tipo de time_tno está garantizado en la especificación C.

El time_ttipo de datos es un tipo de datos en la biblioteca ISO C definido para almacenar valores de hora del sistema. Estos valores se devuelven desde la time() función de biblioteca estándar. Este tipo es un typedef definido en el encabezado estándar. ISO C define time_t como un tipo aritmético, pero no especifica ningún tipo , rango, resolución o codificación en particular. Tampoco se especifican los significados de las operaciones aritméticas aplicadas a los valores de tiempo.

Los sistemas compatibles con Unix y POSIX implementan el time_ttipo como signed integer(normalmente de 32 o 64 bits de ancho) que representa el número de segundos desde el inicio de la época Unix : medianoche UTC del 1 de enero de 1970 (sin contar los segundos intercalares). Algunos sistemas manejan correctamente valores de tiempo negativos, mientras que otros no. Los sistemas que utilizan un tipo de 32 bits time_tson susceptibles al problema del año 2038 .

William Brendel avatar Jan 22 '2009 23:01 William Brendel

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

Se define a $INCDIR/bits/types.htravés de:

# 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
Quassnoi avatar Jan 22 '2009 23:01 Quassnoi

Estándares

William Brendel citó Wikipedia, pero yo lo prefiero de boca del caballo.

C99 N1256 borrador estándar 7.23.1/3 "Componentes del tiempo" dice:

Los tipos declarados son size_t (descritos en 7.17) clock_t y time_t que son tipos aritméticos capaces de representar tiempos.

y 6.2.5/18 "Tipos" dice:

Los tipos enteros y flotantes se denominan colectivamente tipos aritméticos.

POSIX 7 sys_types.h dice:

[CX] time_t será de tipo entero.

donde [CX]se define como :

[CX] Ampliación al estándar ISO C.

Es una extensión porque ofrece una garantía más sólida: los puntos flotantes están descartados.

gcc de una sola línea

No es necesario crear un archivo como lo menciona Quassnoi :

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

En Ubuntu 15.10 GCC 5.2 las dos líneas superiores son:

typedef long int __time_t;
typedef __time_t time_t;

Desglose de comandos con algunas citas de man gcc:

  • -E: "Deténgase después de la etapa de preprocesamiento; no ejecute el compilador correctamente".
  • -xc: Especifique el lenguaje C, ya que la entrada proviene de stdin que no tiene extensión de archivo.
  • -include file: "Procese el archivo como si "#include "file"" apareciera como la primera línea del archivo fuente principal."
  • -: entrada desde la entrada estándar

La respuesta es definitivamente específica de la implementación. Para averiguarlo definitivamente para su plataforma/compilador, simplemente agregue este resultado en algún lugar de su código:

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

Si la respuesta es 4 (32 bits) y sus datos deben ir más allá de 2038 , entonces tiene 25 años para migrar su código.

Sus datos estarán bien si los almacena como una cadena, incluso si es algo simple como:

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

Luego simplemente léalo de nuevo de la misma manera (fread, fscanf, etc. en un int) y tendrá el tiempo de compensación de su época. Existe una solución similar en .Net. Paso números de época de 64 bits entre sistemas Win y Linux sin problemas (a través de un canal de comunicaciones). Eso plantea problemas de orden de bytes, pero ese es otro tema.

Para responder a la consulta de paxdiablo, diría que imprimió "19100" porque el programa fue escrito de esta manera (y admito que lo hice yo mismo en los años 80):

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

La printfdeclaración imprime la cadena fija "El año es: 19" seguida de una cadena rellena con ceros con los "años desde 1900" (definición de tm->tm_year). En el año 2000, ese valor es 100, obviamente. "%02d"rellena con dos ceros pero no se trunca si tiene más de dos dígitos.

La forma correcta es (cambiar solo a la última línea):

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

Nueva pregunta: ¿Cuál es el fundamento de ese pensamiento?

pwrgreg007 avatar Jun 13 '2012 04:06 pwrgreg007

En Visual Studio 2008, el valor predeterminado es __int64a menos que defina _USE_32BIT_TIME_T. Es mejor que simplemente finjas que no sabes cómo se define, ya que puede (y cambiará) de una plataforma a otra.

Eclipse avatar Jan 22 '2009 23:01 Eclipse