Question

J'utilise actuellement un casting explicite à unsigned long long et en utilisant %llu pour l'imprimer, mais depuis size_t a le spécificateur %z, pourquoi ne clock_t pas un?

Il n'y a même pas une macro pour elle. Peut-être que je peux supposer que sur un système x64 (OS et CPU) size_t est de 8 octets de longueur (et même dans ce cas, ils ont fourni %z), mais qu'en est-clock_t?

Était-ce utile?

La solution

Il semble y avoir aucun moyen parfait. La racine du problème est que clock_t peut être entier ou à virgule flottante.

clock_t peut être un type à virgule flottante

Bastien Léonard mentionne Posix (aller le upvote), C99 projet N1256 7.23.1 / 3 dit aussi que:

  

[clock_t est] types arithmétiques capables de représenter les temps

et 6.2.5 / 18:

  

Entier et les types flottants sont collectivement appelés types arithmétiques.

et la norme définit le type arithmétique soit comme des entiers ou des types à virgule flottante.

Si vous divisez par CLOCKS_PER_SEC, utilisez long double

La valeur de retour de clock() est défini par l'implémentation, et la seule façon d'obtenir le sens de la norme est de diviser par CLOCKS_PER_SEC pour trouver le nombre de secondes:

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

Ceci est assez bon, mais pas parfait, pour les deux raisons suivantes:

  • il ne semble pas analogue à intmax_t pour les types de virgule flottante: Comment obtenir le plus grand type de données à virgule flottante précision de implemenation et son spécificateur printf? donc, si un type de point flottant plus grand sort demain, il pourrait être utilisé et briser votre mise en œuvre.

  • si clock_t est un entier, la distribution de flotter est bien défini pour utiliser le flotteur le plus proche possible. Vous risquez de perdre la précision, mais il ne serait pas beaucoup d'importance par rapport à la valeur absolue, et ne se produirait d'énormes quantités de temps, par exemple long int en x86 est le flotteur 80 bits avec 64 bits significatif, ce qui est des millions d'années en quelques secondes.

Aller upvote Lemonad qui a dit quelque chose de similaire.

Si vous pensez qu'il est un entier, utilisez% ju et uintmax_t

Bien que unsigned long long est actuellement le plus grand type entier niveau possible:

il est donc préférable de typer le plus grand entier non signé possible:

#include <stdint.h>

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

uintmax_t est garanti d'avoir la taille de la plus grande taille entière possible sur la machine.

uintmax_t et son spécificateur printf %ju ont été introduits dans C99 et gcc par exemple les met en œuvre.

En prime, cela résout une fois pour toutes la question de savoir comment les types entier de manière fiable printf (ce qui est malheureusement pas nécessairement le cas pour clock_t).

Qu'est-ce qui pourrait mal tourner si elle était double:

  • si elle est trop volumineux pour tenir dans l'entier, un comportement non défini
  • beaucoup plus petit que 1, va s'arrondi à 0 et vous ne verrez rien

Étant donné que ces conséquences sont beaucoup plus dures que l'entier de flotter la conversion, en utilisant float est probablement une meilleure idée.

Sur la glibc 2.21 est un entier

Le manuel dit que l'utilisation double est une meilleure idée:

  

Sur GNU / Linux et les systèmes GNU / Hurd, clock_t est équivalent à long int et CLOCKS_PER_SEC est une valeur entière. Mais dans d'autres systèmes, à la fois clock_t et la macro CLOCKS_PER_SEC peuvent être soit entier ou types à virgule flottante. Casting valeurs de temps CPU pour doubler, comme dans l'exemple ci-dessus, fait en sorte que des opérations telles que le travail de l'arithmétique et l'impression correctement et Consistently quelle que soit la représentation sous-jacente est.

Dans la glibc 2.21:

Voir aussi

Autres conseils

Pour autant que je sache, la façon dont vous faites est le meilleur. Sauf que clock_t peut être un type réel:

  

time_t et clock_t sont entier ou types flottant réel.

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

Il est probablement parce que les tiques horloge n'est pas une unité très bien définie. Vous pouvez le convertir en quelques secondes et l'imprimer en double:

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

La macro CLOCKS_PER_SEC développe en une expression représentant le nombre d'impulsions d'horloge dans une seconde.

La norme C doit accueillir une grande variété d'architectures, ce qui rend impossible de faire d'autres garanties à part le fait que le type d'horloge interne est arithmétique.

Dans la plupart des cas, vous êtes intéressé par des intervalles de temps, donc je convertir la différence de l'horloge impulsions en millisecondes. Un unsigned long est assez grand pour représenter un intervalle de près de 50 jours, même si son 32bit, il devrait donc être assez grand pour la plupart des cas:

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

Une façon est en utilisant la fonction gettimeofday. On peut trouver la différence en utilisant cette fonction:

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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top