如何在C语言中获取时间戳

4

我希望为我的 C 日志获取时间戳。 我已经编写了一个获取时间戳的函数。 但是当我返回该变量时,我得到了不同的值。

我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

char* get_timestamp(){
   time_t rawtime;
   struct tm * timeinfo;
   char buffer[16];
   time (&rawtime);
   timeinfo = localtime (&rawtime);
   strftime (buffer,16,"%G%m%d%H%M%S",timeinfo);
   puts(buffer);
   return buffer; 
}

int main() 
{
   puts(get_timestamp());
   return 0;
}

输出:

20130315204815
Ir?0315204815

有谁能够帮忙解决这个问题吗...非常感谢。


1
你到底为什么要给它打上Boost、C++和C++11的标签? - Daniel Frey
5个回答

6

buffer[16] 是一个局部数组,在 char* get_timestamp() 函数结束时停止存在。然后你返回一个指向不存在的数组的指针。


4
您正在返回指向堆栈变量的指针,因此在函数返回后使用它是无效的:
 char buffer[16];

该函数中将在栈上分配内存。当您返回时,栈将被清理,并且buffer不再有效。使用最小更改,这可能是更好的函数签名:

void get_timestamp( char *buffer, size_t buffLen  )

假设在调用 get_timestamp 前你已经正确分配好了 buffer 的空间。

2
任何类似的函数都应该接受缓冲区大小,因为核心函数(strftime())需要知道缓冲区大小以防止溢出。 - unwind

2

正如其他人所说,您正在使用存储在堆栈上的数据,一旦离开声明它的函数,它就会停止存在。我看到解决此问题的两个简单方法:

选项1:在调用函数中分配缓冲变量,并将指针传递到get_timestamp

void get_timestamp( char *buffer, size_t buffersize ) {
    ....
    strftime (buffer,buffersize,"%G%m%d%H%M%S",timeinfo);
}

int main() 
{
   char buffer[16];
   puts(get_timestamp(buffer,16));
   return 0;
}

注意/编辑:我合并了unwind的非常有价值的备注,关于将缓冲区大小传递到此建议的解决方案中。
选项2:如果您无法或不想更改函数的签名,则可以使用静态变量,但不要忘记静态变量可能会在多线程程序中引起问题。
static char buffer[16];

char* get_timestamp(){
   ... 
}

int main() 
{
   puts(get_timestamp());
   return 0;
}

当然你可以使用malloc,但在这种情况下似乎有些过度,而且比我描述的两种方法更容易出错。


最好将“buffersize”指定为“size_t”。 - Shafik Yaghmour

1
你返回的字符串是一个自动变量。当你退出函数时,访问该变量就不可能了。根据规范,这是未定义的行为。使用malloc来分配字符串,你就没问题了。只是不要忘记在之后释放它。

1
在回答这个问题时,我想要一个简单的、线程友好的函数,不返回char*(通常很烦琐),线程安全,并且能够独立运行。我对返回char*或必须进行管理的指针的函数有一种厌恶感。
下面的函数不调用malloc。
该函数不需要任何参数,并返回一个时间戳。我认为它运行良好。
struct Timestamp {
    time_t seconds;
    long milliseconds;
    char timestring[32];
};


struct Timestamp getTimestamp()
{
char   timebuffer[32]     = {0};
struct timeval  tv        = {0};
struct tm      *tmval     = NULL;
struct tm       gmtval    = {0};
struct timespec curtime   = {0};

struct Timestamp timestamp;

int i = 0;

// Get current time
clock_gettime(CLOCK_REALTIME, &curtime);


// Set the fields
timestamp.seconds      = curtime.tv_sec;
timestamp.milliseconds = round(curtime.tv_nsec/1.0e6);

if((tmval = gmtime_r(&timestamp.seconds, &gmtval)) != NULL)
{
    // Build the first part of the time
    strftime(timebuffer, sizeof timebuffer, "%Y-%m-%d %H:%M:%S", &gmtval);

    // Add the milliseconds part and build the time string
    snprintf(timestamp.timestring, sizeof timestamp.timestring, "%s.%03ld", timebuffer, timestamp.milliseconds); 
}

return timestamp;
}

int main()
{
    char   timebuffer[64]     = {0};
    int i = 0;
    struct timespec sleeptime = {0, 5000000L};

    struct Timestamp timestamp;

    for (i=0; i < 20; i++)
    {
        timestamp = getTimestamp();
        printf("Time is: %s \n", timestamp.timestring);
        nanosleep(&sleeptime, NULL);
    }

    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接