float - type c language
¿Qué es en definitiva un time_t typedef to? (10)
¿Qué es en definitiva un time_t typedef to?
A un código robusto no le importa el tipo.
C especie time_t
para ser un tipo real como double, long long, int64_t, int
, etc.
Incluso podría unsigned
estar unsigned
ya que los valores de retorno de muchas funciones horarias que indican el error no son -1
, sino (time_t)(-1)
- Esta opción de implementación es poco común.
El punto es que el tipo de "necesidad de saber" es raro. El código debe escribirse para evitar la necesidad.
Sin embargo, una "necesidad de saber" común ocurre cuando el código quiere imprimir el time_t
crudo. La conversión al tipo entero más amplio acomodará la mayoría de los casos modernos.
time_t now = 0;
time(&now);
printf("%jd", (intmax_t) now);
// or
printf("%lld", (long long) now);
La conversión a double
o long double
funcionará también, pero podría proporcionar una salida decimal inexacta
printf("%.16e", (double) now);
Busqué en la caja de Linux y vi que era typedef para
typedef __time_t time_t;
Pero no pude encontrar la definición de __time_t.
El artículo de artículo time_t 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 tipo de datos
time_t
es un tipo de datos en la biblioteca ISO C definida para almacenar valores de tiempo del sistema. Dichos valores se devuelven desde la función de bibliotecatime()
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 particular para él. También no especificados son los significados de las operaciones aritméticas aplicadas a los valores de tiempo.Los sistemas Unix y POSIX implementan el tipo
time_t
como unsigned integer
(típicamente 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 los valores de tiempo negativos, mientras que otros no. Los sistemas que usan un tipotime_t
32 bits son susceptibles al problema del año 2038 .
En Visual Studio 2008, su valor predeterminado es un __int64
menos que defina _USE_32BIT_TIME_T
. Es mejor simplemente fingir que no sabe cómo se define, ya que puede (y lo hará) cambiar de una plataforma a otra.
Es un tipo entero con signo de 32 bits en la mayoría de las plataformas heredadas. Sin embargo, eso hace que tu código sufra el error del año 2038 . Por lo tanto, las bibliotecas C modernas deberían definirlo como un int firmado de 64 bits, que es seguro durante unos pocos miles de millones de años.
La respuesta es definitivamente específica de la implementación. Para descubrir definitivamente su plataforma / compilador, solo agregue esta salida 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 van más allá de 2038 , entonces tiene 25 años para migrar su código.
Tus datos estarán bien si almacenas tus datos 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 solo léalo de la misma manera (fread, fscanf, etc. en un int), y tiene su tiempo de offset de época. Existe una solución similar en .Net. Paso sin problemas los números epoch de 64 bits entre los sistemas Win y Linux (a través de un canal de comunicaciones). Eso trae a colación los 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 sentencia printf
imprime la cadena fija "Año es: 19" seguida de una cadena sin relleno con los "años desde 1900" (definición de tm->tm_year
). En 2000, ese valor es 100, obviamente. "%02d"
con dos ceros pero no truncan si tienen más de dos dígitos.
La forma correcta es (cambiar a la última línea solamente):
printf ("Year is: %d/n", local_date_time.tm_year + 1900);
Nueva pregunta: ¿Cuál es la razón de ser de ese pensamiento?
Normalmente encontrará estos typedefs subyacentes específicos de la implementación para gcc en el directorio de cabeceras de bits
o asm
. Para mí, es /usr/include/x86_64-linux-gnu/bits/types.h
.
Puede grep o utilizar una invocación de preprocesador como la sugerida por Quassnoi para ver qué encabezado específico.
[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 en $INCDIR/bits/types.h
mediante:
# 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
time_t
es de tipo long int
en máquinas de 64 bits, sino que es long long int
.
Puede verificar esto en estos archivos de encabezado:
time.h
: /usr/include
types.h
y typesizes.h
: /usr/include/x86_64-linux-gnu/bits
(Las declaraciones a continuación no son una después de otra. Se pueden encontrar en el archivo de encabezado resp. Usando Ctrl + f búsqueda.)
1) En time.h
typedef __time_t time_t;
2) En types.h
# define __STD_TYPE typedef
__STD_TYPE __TIME_T_TYPE __time_t;
3) En 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) De nuevo en 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;
time_t
es simplemente typedef
para 8 bytes ( long long/__int64
) que todos los compiladores y sistemas operativos entienden. En los días anteriores, solía ser solo por long int
(4 bytes) pero ahora no. Si mira el time_t
en crtdefs.h
, encontrará ambas implementaciones pero el sistema operativo usará long long
.
Estándares
William Brendel citó Wikipedia, pero lo prefiero de la boca del caballo.
El borrador estándar C99 N1256 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 los 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á un tipo entero.
donde [CX]
se define como :
[CX] Extensión al estándar ISO C.
Es una extensión porque ofrece una garantía más sólida: los puntos flotantes están fuera.
gcc one-liner
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;