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

任何人都可以帮助解决这个问题...谢谢。

4

5 回答 5

6

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

于 2013-03-15T15:24:04.997 回答
4

您正在返回一个指向堆栈变量的指针,因此在函数返回后使用它是无效的:

 char buffer[16];

将在函数中分配到栈上。当您返回时,堆栈被清理并且buffer不再有效。通过最小的更改,这可能是一个更好的函数签名:

void get_timestamp( char *buffer, size_t buffLen  )

假设您buffer在调用get_timestamp.

于 2013-03-15T15:24:40.243 回答
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,但在这种情况下这似乎有点矫枉过正,而且比我描述的两个修复更容易出错。

于 2013-03-15T15:36:50.863 回答
1

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

于 2013-03-15T15:28:42.830 回答
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;
}
于 2016-12-16T21:08:04.783 回答