格式说明符在C中打印时间(0)

时间:2014-11-21 09:09:53

标签: c time types

我们可以使用以下命令声明一个变量来保存系统的当前时间:

time_t now = time(0);

time(0)也可用于生成随机值:

#define SEED time(0);
srand((unsigned int )SEED);

我的问题是:究竟是什么time(0)。默认情况下,它是以毫秒为单位,类型为long?如果我想打印time(0)的值,我可以使用"%d"将其打印出来吗? (Sicne printf()要求我们传递它所需的类型,但我怎么知道time(0)的类型是什么?)。

如果它是time_t类型,我应该在printf中使用什么格式说明符?

5 个答案:

答案 0 :(得分:4)

time_t由C标准,C11,7.27.1 / 3定义为:

  

[...]这是能够代表时间的真实类型;

这意味着它可以是int,long,unsigned long,double或任何其他真实类型。基本上它是一个实现的选择。同样,它也没有定义time_t返回的单位,C11,7.27.2.4 / 3:

  

时间函数返回实现的最佳近似值   到当前的日历时间。返回值(time_t)( - 1)   如果日历时间不可用。如果timer不是null   指针,返回值也分配给它指向的对象。

您必须阅读您的实施内容。我在Linux上的glibc实现说,time_t返回的单位是秒。因此,您可以将其转换为uintmax_t并打印:

time_t tvalue = time(0);
printf("%ju", (uintmax_t)tvalue);

或者您可以使用difftime()返回double作为两个time_t值之间的差异,这样您就不必担心time_t的基础类型}。

答案 1 :(得分:1)

在大多数系统中,time_t定义的位数与整数相同,且总是正数。

在这种情况下,您可以使用:

 printf("time: %u", (unsigned int) time(0));

答案 2 :(得分:1)

标准没有定义time_t的类型;它只需要是能够代表时间的真实类型。它可以是整数类型或浮点类型(幸运的是它可能很复杂)。并且它不一定是几秒或几毫秒,或任何简单单位。它原则上可以使用位的范围来表示以二进制编码的十进制中的顺序的月,秒,日,小时,分钟和年。最常见的表示形式是32位或64位有符号整数,表示自1970-01-01 00:00:00 UTC以来的秒数。

如果您希望以完全可移植的方式打印time_t值,则可以检测time_t类型的类型:

#include <stdio.h>
#include <time.h>
#include <stdint.h>
int main(void) {
    time_t now = time(NULL);

    printf("At the sound of the tone, the time will be ... \a");

    if ((time_t)1 / 2 != 0) {
        // time_t is a floating-point type; convert to long double
        printf("%Lf\n", (long double)now);
    }
    else if ((time_t)-1 > (time_t)0) {
        // time_t is an unsigned integer type
        printf("%ju\n", (uintmax_t)now);
    }
    else {
        // time_t is a signed integer type
        printf("%jd\n", (intmax_t)now);
    }
}

这假设是C99或更高版本的实现。如果您仍然坚持使用不支持<stdint.h>和/或%ju%jd格式的C99前实施(您可以通过测试{ {1}}),您可以转换为__STDC_VERSION__long而不是unsigned long。 (MinGW可能无法正确处理[u]intmax_t值,但MinGW使用long double的有符号整数类型,因此不存在问题。)

这将打印一个没有意义的原始值,除非您碰巧知道time_t的表示方式(的类型和表示当前时间的方式) 。在我的系统上,当前时间是time_t,这是自1970-01-01 00:00:00 UTC(非常常见的表示)以来的秒数。

如果您想知道它的时间而不是1416589039函数返回的原始值,您应该使用time()中的函数来生成人类 - 可读的当前时间表示。例如:

<time.h>

打印(目前在我的系统上):

#include <stdio.h>
#include <time.h>
#include <stdint.h>
int main(void) {
    time_t now = time(NULL);
    char s[100];
    strftime(s, sizeof s, "%F %H:%M:%S %Z", localtime(&now));
    printf("The time is now %s\n", s);
}

答案 3 :(得分:0)

如前所述,标准没有规定time_t是什么。如果您想确保以便携方式使用它,首先将其转换为long,然后将其打印为long。这样,即使当时仍有32位架构可用,您的程序也不会遇到2038年的问题:-) ...

time_t t = time(NULL);
long lt = (t > 0) ? t : (unsigned int) t;
printf("%ld", lt);

它应该适用于time_t是32位有符号整数或64位整数。当time_t为负64位整数时,我的formule将会中断,但在那时请与我联系,然后我应该明智地找到更好的解决方案: - )

编辑:

正如chux所指出的,如果int只有16位,这就很糟糕。即使是丑陋的方式,这也是一种强大的方式

union {
    long l;
    unsigned char[1] c;
} ul;
time_t t = time(NULL);
ul.l = 0;
ul.c[0] = 255;
if (ul.l < 0) { /* endianness test */
    ul.l = 0;
    memcpy(&ul.l, t&, sizeof(time_t));
}
else {
    ul.l = 0;
    memcpy(&ul.l + sizeof(long) - sizeof(time_t), &t, sizeof(time_t));
}
printf("%lu", (unsigned long) ul.l);

它应该适用于sizeof(long)>=sizeof(time_t)

提供的任何配置

编辑2:

chux的提案似乎适用于任何合理的案例。肯定有病态的情况可能会破坏但正常实施

time_t t = time(NULL);
long lt = (t > 0) ? t : t * 1u;
printf("%ld", lt);

应该给出正确的结果。

答案 4 :(得分:0)

查看时间函数的头文件, 你会看到参数可以是NULL或time_t变量的地址之一。

参数和返回值的time()函数结果是自纪元以来的经过时间(以秒为单位)(当前为1970年1月1日00:00 am UTC。)值的大小(在旧系统上) )是4个字节(32位)。使用最近的RTC(RealTimeClock)硬件,值'可能'是8字节(64位)。在任何情况下,值都是自纪元以来的秒数。

4字节时间值将在2038年溢出,因此正在努力     1)使时间值更大或     2)将纪元时间转移到2000年1月1日00:00 am。        (使用旧硬件时的临时修复)

将时间值更改为8个字节是当前首选方法。

这是谷歌的特定报价:

“在2038年1月19日03:14:08 UTC,32位版本的Unix时间戳将停止工作”以引用其余的引用:32位值将溢出。

处理时间的函数,如localtime()strtotime()。等,并且相关的结构,如tm,被设置为使用他们正在运行的系统从time()函数返回的内容。

时间函数中值的所有处理都应该使用可用函数来完成,而不是处理原始值。