localtime和gmtime这两个函数采用了time.h中的一个tm结构体:
struct tm
{
int tm_sec; /* Seconds. [0-60] (1 leap second) */
int tm_min; /* Minutes. [0-59] */
int tm_hour; /* Hours. [0-23] */
int tm_mday; /* Day. [1-31] */
int tm_mon; /* Month. [0-11] */
int tm_year; /* Year - 1900. */
int tm_wday; /* Day of week. [0-6] */
int tm_yday; /* Days in year.[0-365] */
int tm_isdst; /* DST. [-1/0/1]*/
};
这两个函数的原型为:
struct tm *localtime(const time_t *timep);
struct tm *gmtime(const time_t *timep);
例1:
---------------------------------------------------------
#include <ctime>
#include <iostream>
using namespace std;
void cur_time(void)
{
char *wday[] = {"星期天", "星期一","星期二","星期三","星期四","星期五","星期六"};
time_t timep;
struct tm *p;
time(&timep);
p = localtime(&timep);
printf("%d年%2d月%2d日", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday);
printf("%s%2d:%2d:%2d/n", wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec);
}
int main()
{
cur_time();
return 0;
}
---------------------------------------------------------
运行结果为:
2008年12月26日星期三 11:07:15
例2《一个关于localtime函数的讨论》:
---------------------------------------------------------
#include <ctime>
#include <iostream>
using namespace std;
struct tm* get_local_time()
{
struct tm *now;
time_t timep;
time(&timep);
now = localtime(&timep);
return now;
}
int main()
{
struct tm *temp;
struct tm *temp1;
//struct tm tm1;
//struct tm tm2;
temp = get_local_time();
//tm1 = *temp;
printf("%d:%2d:%2d/n", temp->tm_hour, temp->tm_min, temp->tm_sec);
//目的是停顿一下
getchar();
//tm2 = *temp1;
temp1 = get_local_time();
printf("%d:%2d:%2d/n", temp->tm_hour, temp->tm_min, temp->tm_sec);
printf("%d:%2d:%2d/n", temp1->tm_hour, temp1->tm_min, temp1->tm_sec);
//printf("%d:%2d:%2d/n", temp->tm_hour, temp->tm_min, temp->tm_sec);
//printf("%d:%2d:%2d/n", temp1->tm_hour, temp1->tm_min, temp1->tm_sec);
return 0;
}
---------------------------------------------------------
运行结果为:
最后两个printf()结果是一样的
其原因如下:
这是localtime函数实现的问题。
该函数返回的是一个指针,表示某一个地址。大家知道,如果是一个非静态的局部变量,返回它的地址是错误的做法,因为非静态的局部变量在函数返回时,已经被销毁了,它的地址成为无用的地址。因此localtime函数返回的指针只有以下三种可能:要么是一个静态变量的地址,要么是一个全局变量的地址,或者是使用malloc等函数在堆上分配的空间。
对于最后一种情况,因为标准并没有规定可以对localtime返回的地址进行free,所以如果localtime函数是使用malloc函数分配空间的话,程序员不会使用free函数去释放它,因此造成内存泄露,这是不好的做法。
前两种情况其实是非常相似的,这里仅以第一种情况来做说明。如果localtime函数使用静态变量,则它大致像下面这个样子:
struct tm* localtime(const time_t* ptr)
{
static struct tm ret;
// 在这里计算并得到ret的值
return &ret;
}
如果真是这样的话,不论调用多少次localtime,则它返回的地址都是一样的。只是地址中保存的内容可能不同而已。
比较正确的做法是:
struct tm* temp;
struct tm* temp1;
struct tm tm1;
struct tm tm2;
temp = get_local_time();
tm1 = *temp;
sleep(3);
temp1 = get_local_time();
tm2 = *temp1;
则虽然可能有temp == temp1,但是tm1和tm2则会不同。
静态变量在进行多线程编程时是危险的,因此微软搞出了一个新的localtime_s函数来取代localtime函数(新版本的VC有这个函数,VC 6.0则似乎没有,linux系统我并不清楚)。这两个函数在功能上一致,只是localtime返回地址,而localtime_s是传入一个地址,让函数填充其内容。后者不需要使用静态变量,在多线程的情况下更安全。
例3 用localtime_s()代替localtime():
---------------------------------------------------------
#include <ctime>
#include <iostream>
using namespace std;
int main()
{
struct tm newtime;
time_t timep;
errno_t err;
time(&timep);
err = localtime_s(&newtime, &timep);
if (err)
{
printf("Invalid argument to localtime_s.");
return;
}
else
{
printf("%d:%2d:%2d/n", newtime.tm_hour, newtime.tm_min, newtime.tm_sec);
}
return 0;
}
---------------------------------------------------------
例4 gmtime()函数
---------------------------------------------------------
#include <ctime>
#include <iostream>
using namespace std;
void cur_time(void)
{
char *wday[] = {"星期天", "星期一","星期二","星期三","星期四","星期五","星期六"};
time_t timep;
struct tm *p;
time(&timep);
p = gmtime(&timep);
printf("%d年%2d月%2d日", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday);
printf("%s%2d:%2d:%2d/n", wday[p->tm_wday], p->tm_hour + 8, p->tm_min, p->tm_sec);
}
int main()
{
cur_time();
return 0;
}