您的位置:首页 > 其它

localtime函数中的返回指针的思考

2011-11-25 14:30 183 查看
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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: