Además de la diferencia de precisión, ¿cuáles son las diferencias entre struct timeval y struct timespec ? Si necesito menos precisión que µs (digamos, milisegundos), ¿por qué usaría uno sobre el otro?
En mi compilador (gcc para ARM):
/* POSIX.1b structure for a time value. This is like a `struct timeval' but has nanoseconds instead of microseconds. */ struct timespec { __time_t tv_sec; /* Seconds. */ __syscall_slong_t tv_nsec; /* Nanoseconds. */ }; /* A time value that is accurate to the nearest microsecond but also has a range of years. */ struct timeval { __time_t tv_sec; /* Seconds. */ __suseconds_t tv_usec; /* Microseconds. */ }; Con __syscall_slong_t y __suseconds_t definidos como una "palabra larga".
Creo que en realidad es solo una cuestión de [in]compatibilidad de API. Las llamadas POSIX-y como pselect() y clock_gettime() usan struct timespec . Varias llamadas al sistema de archivos como utimes() , y algunas llamadas variadas de Linux como gettimeofday() y select() , usan struct timeval . Generalizando ampliamente a partir de unas pocas páginas man, sospecho que struct timeval tiene un legado BSD mientras que struct timespec es POSIX.
Si está realizando mediciones de intervalos, no hay razón para no aprovechar la precisión adicional de clock_gettime() , aunque tenga en cuenta que generalmente es el hardware, no el archivo de encabezado, lo que limita la precisión de la medición. Dividir por un millón para fines de visualización no es ni mejor ni peor que dividir por mil. (Además, Mac OS X anterior a 10.12 no clock_gettime() .
Pero si está manipulando mucho el tiempo de los archivos, podría tener más sentido usar la struct timeval utilizada en las API como utimes() . struct timeval también tiene algunas funciones de comparación en Linux, BSD y Mac OS X, por ejemplo, timercmp() , timersub() (nuevamente, consulte las páginas man).
Tomaría la decisión en función de las API que pretende utilizar, en lugar de las estructuras en sí. (O escriba una clase contenedora con métodos de conversión si es necesario).
Ambos están definidos por AFAIK para POSIX.1-2001, por lo que desde el punto de vista de la portabilidad, no importa cuál use. La respuesta más simple es: use lo que necesite para la API que desea llamar.
PODRÍA haber un beneficio de tamaño dependiente de la plataforma usando struct timeval :
El tipo suseconds_t debe ser un tipo entero con signo capaz de almacenar valores al menos en el rango [-1, 1000000].
en struct timespec el segundo miembro es de tipo long . Un int sería suficiente en una plataforma de 32 bits para cumplir con los requisitos de suseconds_t . Pero, en un sistema de 64 bits, time_t suele ser de 64 bits, lo que obliga a la estructura a rellenar hasta 16 bytes de todos modos. Entonces, un beneficio de tamaño es... improbable.
Personalmente, no uso ninguno. Prefiero expresar el tiempo como un simple int64_t porque eso hace que los cálculos de tiempo sean muy simples y, si es necesario, volver a convertir a struct timeval o struct timespec tampoco es un problema. Incluso si desea una precisión de nanosegundos, int64_t puede expresar un lapso de casi 585 años. Si solo necesita milisegundos, tiene un lapso de casi 585 millones de años.