Je veux rendre mon code plus indépendant de la plateforme/de l'implémentation. Je ne sais pas ce qu'un time_t
sera implémenté comme sur la plateforme lors de la compilation du code. Comment connaître le type de t
pour déterminer le spécificateur de format à utiliser?
...
time_t t = time(NULL);
printf("%s", t);
...
Généralement, la façon d'afficher la valeur d'un time_t
consiste à décomposer ses composants en struct tm
en utilisant gmtime
ou localtime
et affichez-les ou convertissez-les comme vous le souhaitez avec strftime
, ou ctime
pour passer directement de time_t
à une chaîne indiquant l'heure locale.
Si vous voulez voir la valeur brute dans un certain but, la norme C spécifie que time_t
est réel, ce qui signifie qu'il est entier ou à virgule flottante (C 2011 (N1570) 6.2.5 17). Par conséquent, vous devriez pouvoir le convertir en double
et l'imprimer. Il est possible que time_t
peut représenter des valeurs que double
ne peut pas, donc vous devrez peut-être vous en prémunir si vous voulez faire attention aux implémentations exotiques. Puisque difftime
renvoie la différence de deux time_t
objets comme double
, il semble que C ne supporte pas vraiment time_t
avec plus de précision qu'un double
.
Habituellement, vous pouvez utiliser un transtypage pour convertir l'opérande en un type dont vous connaissez le bon format.
Votre solution proposée:
time_t t = time(NULL);
printf("%s", t);
clairement pas fonctionnera, puisque time_t
est un type numérique, pas char*
.
Nous savons, en général, que time_t
Est un type arithmétique. Quelque chose comme ça:
printf("%ld\n", (long)t);
est susceptible de fonctionner sur la plupart des systèmes. Il peut échouer (a) si time_t
Est un type non signé pas plus large que unsigned long
Et que la valeur actuelle de t
dépasse LONG_MAX
, Ou (b) si time_t
Est un type à virgule flottante.
Si vous avez le support C99, vous pouvez utiliser long long
, Ce qui est un peu mieux:
printf("%lld\n", (long long)t);
Si vous voulez vraiment aller trop loin avec la portabilité, vous pouvez détecter le type de type time_t
:
if ((time_t)-1 > 0) {
// time_t is an unsigned type
printf("%ju\n", (uintmax_t)t);
}
else if ((time_t)1 / 2 > 0) {
// time_t is a signed integer type
printf("%jd\n", (intmax_t)t);
}
else {
// time_t is a floating-point type (I've never seen this)
printf("%Lg\n", (long double)t);
}
Vous pouvez souhaiter ajuster le format %Lg
À quelque chose comme %Lf
Ou %.10Lf
, Selon le format de sortie que vous souhaitez.
Encore une fois, cela suppose la prise en charge de C99 - et vous aurez besoin de #include <stdint.h>
Pour rendre uintmax_t
Et intmax_t
Visibles.
time_t
Et clock_t
Sont un peu inhabituels, en ce sens que la norme indique seulement qu'ils sont de type arithmétique capables de représenter les temps. (En principe, il pourrait s'agir de types complexes, mais je dirais qu'ignorer cette possibilité en vaut le risque.)
Dans la plupart des autres cas, vous saurez probablement si un type donné est signé, non signé ou à virgule flottante, et vous pouvez simplement convertir le type le plus large de ce type.
Notez que si vous ne savez pas comment time_t
Est représenté, vous ne comprendrez probablement pas non plus la sortie du printf
(comme 1379375215
) - à moins que votre objectif est de comprendre cela.
(Si vous programmiez en C++ plutôt qu'en C, std::cout << t << "\n";
Utiliserait automatiquement la bonne surcharge operator<<
.)
Si vous voulez une sortie lisible par l'homme (comme Mon 2013-09-16 16:46:55 PDT
), Vous voudrez utiliser l'une des fonctions de conversion déclarées dans <time.h>
, Comme asctime()
ou strftime()
.
Vous pouvez utiliser difftime()
pour obtenir un double
:
time_t t = time(NULL);
printf("seconds 1970->now: %.f\n", difftime(t, (time_t) 0));
C'est simple et je pense que c'est portable.
La norme C indique que time_t
Sera un "type réel" (c'est-à-dire un type entier ou un type à virgule flottante, bien qu'en pratique ce soit toujours un type entier).
Avec time_t
, Le mieux est de le formater avec strftime()
après l'avoir analysé avec localtime()
ou gmtime()
- cela peut être fait de manière portable.
Malheureusement, vous devez déterminer par un mécanisme quel est le spécificateur de format correct. Vous pouvez utiliser PRI_[Xxodi]_time
Et SCN_[Xxodi]_time
Ou quelque chose de similaire comme non standard mais proche de la norme (sans piétiner l'espace de noms réservé - c'est-à-dire les noms commençant par PRI ou SCN suivi d'une lettre minuscule ou X). Vous utilisez un mécanisme pour spécifier que ... encapsulant les informations non transférables en un seul endroit.