Reputation: 2317
I was expecting the following code should print different time stamps t1 and t2, however the result shows t1 and t2 are the same. Where did I make the mistake?
#include<iostream>
#include<ctime>
using namespace std;
int main()
{
time_t t1 = time(NULL);
cout << "time now " << ctime(&t1) << endl;
time_t t2 = t1 + 10000.0;
cout << "time now " << ctime(&t1) << endl << " time later " << ctime(&t2) <<endl;
}
Result:
time now Thu Apr 28 20:37:03 2016
time now Thu Apr 28 20:37:03 2016
time later Thu Apr 28 20:37:03 2016
Upvotes: 5
Views: 2466
Reputation: 118292
The answer to your question can be found in the manual page for the ctime() function:
The return value points to a statically allocated string which might be overwritten by subsequent calls to any of the date and time functions.
ctime() returns a pointer to an internal buffer it uses. Every time it's called, it returns a pointer to the same buffer:
cout << "time now " << ctime(&t1) << endl << " time later " << ctime(&t2) <<endl;
For this line of code, your compiler generated code that calls ctime()
twice, then executes the <<
operator. But on the second call to ctime()
, it overwrote the buffer with the second time, so when the <<
operator formats the output, because the result of the first call to ctime()
is the same pointer, and the buffer that it points to has been overwritten by the second call to ctime()
, you get the same time printed twice.
Thank you for posting a Minimal, Complete, and Verifiable example.
Upvotes: 4
Reputation: 75062
Quote from N1570 7.27.3 Time conversion functions:
Except for the strftime function, these functions each return a pointer to one of two types of static objects: a broken-down time structure or an array of char. Execution of any of the functions that return a pointer to one of these object types may overwrite the information in any object of the same type pointed to by the value returned from any previous call to any of them and the functions are not required to avoid data races with each other.
This suggests that the contents pointed by what is returned from ctime()
can be overwritten by another call of ctime()
, so you will have to copy the result to use the result in one expression with no sequence point in that.
Try this:
#include<iostream>
#include<ctime>
#include<string>
using namespace std;
int main()
{
time_t t1 = time(NULL);
cout << "time now " << ctime(&t1) << endl;
time_t t2 = t1 + 10000.0;
string t1s = ctime(&t1);
string t2s = ctime(&t2);
cout << "time now " << t1s << endl << " time later " << t2s <<endl;
}
Upvotes: 2
Reputation: 302748
What is ctime
actually returning? From cppreference:
Pointer to a static null-terminated character string holding the textual representation of date and time. The string may be shared between
std::asctime
andstd::ctime
, and may be overwritten on each invocation of any of those functions.
It likely works out that on your compiler, the later ctime()
gets called first, then the newer ctime()
, then both operator<<()
s get evaluated - which emit the same char*
. As a result of the unspecified order, your code has undefined behavior. On some compilers, it could work as you hoped it would! On yours, it happens not to.
If you separate out the two calls:
cout << "time now " << ctime(&t1) << endl;
cout << " time later " << ctime(&t2) <<endl;
you'd definitely and consistently see different values.
Upvotes: 3