¿Para qué es time_t, en última instancia, una definición de tipo?
Busqué en mi caja de Linux y vi este typedef:
typedef __time_t time_t;
Pero no pude encontrar la __time_t
definición.
El artículo time_t de Wikipedia arroja algo de luz sobre esto. La conclusión es que el tipo de time_t
no está garantizado en la especificación C.
El
time_t
tipo 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 latime()
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_t
tipo comosigned 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 bitstime_t
son susceptibles al problema del año 2038 .
[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.h
travé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
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 printf
declaració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?
En Visual Studio 2008, el valor predeterminado es __int64
a 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.