【问题标题】:c-time function returns strange valuesc-time 函数返回奇怪的值
【发布时间】:2019-05-29 10:38:06
【问题描述】:

我正在使用 C 中的代码,它使用以下内容从服务器获取时间:

(这是一个很短的版本,代码的其他部分和函数使用time、ftime和localtime函数来获取时间)。

struct  tm *stiempo;
long    ltiempo;
FILE * arch2;

int main()
{
  print_error_time();
}


void print_error_time()
{
   time (&ltiempo);
   stiempo = localtime (&ltiempo);
   fprintf (arch2, "%02.2ld/%02.2ld/%02.2ld, \t %02.2ld:%02.2ld:%02.2ld", stiempo->tm_mday, (stiempo->tm_mon + 1), (stiempo->tm_year + 1900), stiempo->tm_hour, stiempo->tm_min, stiempo->tm_sec);
}

有时它工作得很好,但有时,当时间打印到文件中时,我会得到这样的东西:

   21/08/2018,   15:48:7956003943165722682
   21/08/2018,   15:50:7956003943165722667
   21/08/2018,   15:51:7956003943165722649

有谁知道是什么导致了这种行为,或者什么会影响使它们返回这些值的时间函数?

【问题讨论】:

  • arch2 FILE 指针未指向任何 FILE 对象。
  • 您在fprintf() 中使用了错误的格式说明符,这是未定义的行为。
  • struct tm 中的大多数字段不是long,而是int,并且在64 位机器上使用%ld 打印它们会导致不可预知的行为。您可以使用 %.2d 或 %02d 来获得您想要的结果(可能),但也许您应该在一年中使用 4 而不是 2(尽管它不会对 2 造成损害)。在 32 位机器上,您可以使用 sizeof(int) == sizeof(long)。此外,出于同样的原因,Win64 可能没问题。
  • 这可能是唯一的原因吗?我正在尝试在另一台机器上复制该错误,但我不能。我正在运行相同的代码,它以应有的方式打印时间,甚至使用 %ld 打印
  • @Fausto:未定义行为的问题在于允许代码按预期工作和按预期工作,两者都是正确的,因为官方要求未定义。您可以看到它在机器 A 上运行而在机器 B 上失败的一种方法是机器 A 是 32 位而机器 B 是 64 位。如果工作机器是 Windows 64 位而非工作机器不是,您也可能会遇到问题。如果一台机器上的 CPU 是 little-endian 而另一台机器上的 CPU 是 big-endian,您可能会遇到问题。你还没有确定你的两台机器有多相似。

标签: c time localtime


【解决方案1】:

来自localtime:

Broken-down time is stored in the structure tm which is defined in <time.h> as follows:

struct tm {
    int tm_sec;         /* seconds */
    int tm_min;         /* minutes */
    int tm_hour;        /* hours */
    int tm_mday;        /* day of the month */
    int tm_mon;         /* month */
    int tm_year;        /* year */
    int tm_wday;        /* day of the week */
    int tm_yday;        /* day in the year */
    int tm_isdst;       /* daylight saving time */
};

所有tm 结构成员都是int 类型,您在fprintf() 中为它们使用格式说明符%ld。相反,您应该使用%d 格式说明符。

来自 C 标准#7.21.6.1p9

9 如果转换规范无效,则行为未定义。282) 如果任何参数不是相应转换规范的正确类型,则行为未定义。

【讨论】:

  • 这可能是唯一的原因吗?我正在尝试在另一台机器上复制该错误,但我不能。我正在运行相同的代码,它以应有的方式打印时间,甚至使用 %ld 打印
  • @Fausto 未定义的行为包括它可能执行不正确(崩溃或静默生成不正确的结果),或者它可能偶然地完全按照程序员的意图执行。在我的机器上,使用%ld,我得到了 - 03/01/2019, 01:4294967309:37 结果。
猜你喜欢
  • 2012-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 2020-10-01
  • 1970-01-01
相关资源
最近更新 更多