Pregunta

Actualmente estoy usando una conversión explícita a unsigned long long y el uso de %llu imprimirlo, pero desde size_t tiene el especificador %z, ¿por qué no clock_t tener uno?

No hay ni siquiera una macro para ello. Tal vez pueda suponer que en un sistema x64 (OS y CPU) size_t es de 8 bytes de longitud (e incluso en este caso, han proporcionado %z), pero ¿qué pasa clock_t?

¿Fue útil?

Solución

No parece haber ninguna manera perfecta. La raíz del problema es que clock_t puede ser entero o de coma flotante.

clock_t puede ser un tipo de coma flotante

Bastien Léonard menciona de POSIX (GO le upvote), C99 N1256 proyecto 7.23.1 / 3 dice también que:

  

[clock_t es] tipos aritméticas capaces de representar veces

y 6.2.5 / 18:

  

Entero y tipos flotantes se denominan colectivamente tipos aritméticos.

y el estándar define tipo aritmético, ya sea como números enteros o tipos de coma flotante.

Si va a dividir por CLOCKS_PER_SEC, el uso a largo doble

El valor de retorno de clock() se define la aplicación, y la única manera de conseguir significado estándar fuera de él es dividir por CLOCKS_PER_SEC para encontrar el número de segundos:

clock_t t0 = clock();
/* Work. */
clock_t t1 = clock();
printf("%Lf", (long double)(t1 - t0));

Esto es bastante bueno, aunque no es perfecto, por las dos razones siguientes:

  • no parece haber ningún análogo a intmax_t para este tipo de punto flotante: ¿Cómo obtener la mayor precisión flotante tipo de datos punto de implemenation y su especificador printf? lo tanto, si un tipo de coma flotante más grande sale mañana, podría ser usada y romper su aplicación.

  • si clock_t es un número entero, el reparto a flotar está bien definida para utilizar el flotador más cercano posible. Es posible que pierda precisión, pero no importaría mucho en comparación con el valor absoluto, y sólo se le ocurriría a enormes cantidades de tiempo, por ejemplo, long int en x86 es el flotador 80 bits con 64 bits significativos, que tiene millones de años en cuestión de segundos.

Ir upvote lemonad que dijo algo similar.

Si usted supone que es un entero, utiliza% ju y uintmax_t

Aunque unsigned long long es actualmente el mayor tipo entero estándar posible:

lo que es mejor para encasillado a la mayor tipo entero sin signo posible:

#include <stdint.h>

printf("%ju", (uintmax_t)(clock_t)1);

uintmax_t está garantizado para tener el tamaño del mayor tamaño posible número entero en la máquina.

uintmax_t y su %ju printf especificador se introdujeron en c99 y gcc por ejemplo las implementa.

Como beneficio adicional, esto resuelve de una vez por todas la cuestión de cómo fiable printf número entero tipos (que por desgracia no es el necesariamente el caso de clock_t).

¿Qué podría salir mal si se trataba de un doble:

  • si es demasiado grande para encajar en el número entero, comportamiento indefinido
  • mucho menor que 1, conseguirá redondeado a 0 y no verá nada

Dado que esas consecuencias son mucho más duras que el número entero a flote la conversión, mediante flotador es probablemente una mejor idea.

En glibc 2.21 es un número entero

El manual dice que el uso de double es una idea mejor:

  

En GNU / Linux y sistemas GNU / Hurd, clock_t es equivalente a largo int y CLOCKS_PER_SEC es un valor entero. Pero en otros sistemas, tanto clock_t y la macro CLOCKS_PER_SEC pueden ser ya sea entero o tipos de punto flotante. Fundición valores de tiempo de CPU para duplicar, como en el ejemplo anterior, se asegura de que las operaciones tales como la aritmética y la impresión trabajo correctamente y consiste delntly no importa lo que la representación subyacente es.

En glibc 2.21:

Ver también

Otros consejos

Por lo que yo sé, la forma en que está haciendo es la mejor. Excepto que clock_t puede ser un tipo real:

  

time_t y clock_t serán entero o real flotante tipos.

http://www.opengroup.org/onlinepubs/ 009695399 / basedefs / sys / types.h.html

No es probablemente debido a impulsos del reloj es una unidad muy bien definido. Puede convertirlo en segundos e imprimirlo como un doble:

time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);

La macro CLOCKS_PER_SEC expande una expresión que representa el número de ciclos de reloj en un segundo.

El estándar C tiene que acomodar una amplia variedad de arquitecturas, lo que hace imposible hacer cualquier garantías adicionales aparte del hecho de que el tipo de reloj interno es aritmética.

En la mayoría de los casos, usted está interesado en intervalos de tiempo, así que me gustaría convertir la diferencia en el reloj avanza a milisegundos. Un unsigned long es lo suficientemente grande como para representar un intervalo de casi 50 días, incluso si es de 32 bits, por lo que debe ser lo suficientemente grande para la mayoría de los casos:

clock_t start;
clock_t end;
unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;

Una forma es mediante el uso de la función gettimeofday. Uno puede encontrar la diferencia de usar esta función:

unsigned long  diff(struct timeval second, struct timeval first)
{
    struct timeval  lapsed;
    struct timezone tzp;
    unsigned long t;

    if (first.tv_usec > second.tv_usec) {
        second.tv_usec += 1000000;
        second.tv_sec--;
    }

    lapsed.tv_usec = second.tv_usec - first.tv_usec;
    lapsed.tv_sec  = second.tv_sec  - first.tv_sec;
    t = lapsed.tv_sec*1000000 + lapsed.tv_usec;

    printf("%lu,%lu - %lu,%lu = %ld,%ld\n",
           second.tv_sec, second.tv_usec,
           first.tv_sec,  first.tv_usec,
           lapsed.tv_sec, lapsed.tv_usec);

    return t;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top