在cout上打印时间时奇怪的C ++行为

时间:2013-07-10 15:39:20

标签: c++

运行以下代码:

  1 #include <iostream>
  2 int main(int argc, char** argv)
  3 {
  4     time_t t1 = time(0);
  5     time_t t(0);
  6     std::cout<<"BUG LINE"<<std::endl<< ctime(&t) << ctime(&t1) ;
  7     std::cout<<"PRINTS FINE HERE"<<std::endl;
  8     std::cout<< ctime(&t);
  9     std::cout<< ctime(&t1);
 10     return 0;
 11 }

构建:g ++ test1.cpp

Output:
./a.out
BUG LINE
Thu Jan  1 01:00:00 1970
Thu Jan  1 01:00:00 1970
PRINTS FINE HERE
Thu Jan  1 01:00:00 1970
Wed Jul 10 16:31:48 2013

为什么流在代码的#6中变得奇怪?

4 个答案:

答案 0 :(得分:7)

http://www.cplusplus.com/reference/ctime/ctime/

  

返回的值指向内部数组,其有效性或值可能会被后续调用asctimectime 更改。

http://en.cppreference.com/w/cpp/chrono/c/ctime

  

字符串可以在std::asctimestd::ctime之间共享,可能会在每次调用任何这些函数时被覆盖

在您的示例中,在第6行,首先评估ctime(&t1),然后覆盖字符串的ctime(&t)(首先评估的是未指定的,编译器通常以相反的顺序进行评估(经常,并非总是如此)。

TL; DR:阅读文档可能会有所帮助。

答案 1 :(得分:3)

函数ctime返回一个static字符串缓冲区 - 所以返回的字符串每次都是完全相同的字符串),这意味着在同一行上多次调用它会产生未定义的行为(因为C和C ++标准没有说明调用的顺序是什么。

解决方案是调用两个不同的语句(两者之间有;),或者使用reentrant-safe变体,在这里传入缓冲区以存储结果),例如: ctime_r

答案 2 :(得分:1)

这里的问题是ctime()使用内部分配的char数组,每次调用ctime()时都会对其进行修改。

这里的另一个问题是您的ctime()可以在该表达式中以任何顺序进行评估。所以这里发生的是第6行的两个都被评估,但显然第二个是第二个。然后从左到右应用运算符,但是对ctime的两个调用都已经过评估,最左边的调用是在之后完成的,现在两个字符串都指向相同的东西。

如果您将它们放在不同的行上,您将获得预期的行为。

http://www.cplusplus.com/reference/ctime/ctime/

  

包含a中日期和时间信息的C字符串   人类可读的格式。

     

返回的值指向其有效性或值的内部数组   任何后来对asctime或ctime的调用都可能会改变。

答案 3 :(得分:0)

  

返回的值指向其有效性或值的内部数组   任何后来对asctime或ctime的调用都可能会改变。

这正是这里发生的事情。在该行中对ctime的两次调用之一在另一行之前执行,但在cout可以打印它们之前都执行。由于它们(可能)返回相同的临时字符缓冲区,因此在cout进入打印时会得到相同的结果。