ctime函数使用遇到的坑

今天在使用ctime函数遇到了一个问题,示例代码如下:

const char *date;              //获取当前的时间
time_t now = time(NULL);
date = ctime(&now);
delete_crlf(date);             //此函数是为了删除date的换行符
printf("%s\n", date);

sleep(2);
now = time(NULL);
ctime(&now);
printf("%s\n", date);

原本我的目的是为了打印出当前的时间,因此我对于这两个输出的期望都应该是

Mon Nov 13 15:28:25 2017

但最终结果居然是

Mon Nov 13 15:28:25 2017

Mon Nov 13 15:28:27 2017

发现两次打印的结果居然不一致,这是为什么呢?
在http://www.cplusplus.com/reference/ctime/ctime/上查阅函数信息时发现:
The returned value points to an internal array whose validity or value may be altered by any subsequent call to asctime or ctime.
大意是说,它的返回值指向了一个内部数组,而它的值或有效性可能会被之后的函数调用ctime或asctime改变。

函数的具体实现如下:

/* 这里的函数在GNU libc的locale/C-time.c中定义  */
#include 
#include 

extern const struct locale_data _nl_C_LC_TIME attribute_hidden;

#define ab_day_name(DAY) (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)+(DAY)].string)
#define ab_month_name(MON) (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)+(MON)].string)

static const char format[] = "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n";
//result存储最终结果
static char result[ 3+1+3+1+20+1+20+1+20+1+20+1+20+1+1];

static char * asctime_internal (const struct tm *tp, char *buf, size_t buflen)
{
  if (tp == NULL)
    {
      __set_errno (EINVAL);
      return NULL;
    }
  if (__builtin_expect (tp->tm_year > INT_MAX - 1900, 0))
    {
    eoverflow:
      __set_errno (EOVERFLOW);
      return NULL;
    }
  int n = __snprintf (buf, buflen, format,
              (tp->tm_wday < 0 || tp->tm_wday >= 7 ?
               "???" : ab_day_name (tp->tm_wday)),
              (tp->tm_mon < 0 || tp->tm_mon >= 12 ?
               "???" : ab_month_name (tp->tm_mon)),
              tp->tm_mday, tp->tm_hour, tp->tm_min,
              tp->tm_sec, 1900 + tp->tm_year);
  if (n < 0)
    return NULL;
  if (n >= buflen)
    goto eoverflow;
  return buf;
}

char * __asctime_r (const struct tm *tp, char *buf)
{
  return asctime_internal (tp, buf, 26);
}

weak_alias (__asctime_r, asctime_r)

char * asctime (const struct tm *tp)
{
  return asctime_internal (tp, result, sizeof (result));
}

libc_hidden_def (asctime)

char * ctime (const time_t *t)
{
  return asctime (localtime (t));
}

可以看到,ctime的返回值是result这个静态数组的首地址,因此每一次的ctime调用都会覆盖原来的值。这也就解释了上述情况的问题。
所以说,如果要获取当前人类可读的时间形式,最好是通过定义一个新的字符数组去储存,而不要去定义字符指针,因为你指向的内容很可能会因为其他方式改变了。

你可能感兴趣的:(C-C++)