【问题标题】:timestamp in c with milliseconds precisionc 中的时间戳,精度为毫秒
【发布时间】:2014-03-20 05:46:16
【问题描述】:

我对 C 编程比较陌生,我正在做一个需要非常准确的项目;因此我尝试写一些东西来创建一个毫秒精度的时间戳。

这似乎可行,但我的问题是这种方式是否正确,还是有更简单的方式?这是我的代码:

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

void wait(int milliseconds)
{
    clock_t start = clock();
    while(1) if(clock() - start >= milliseconds) break;
}

int main()
{
    time_t now;
    clock_t milli;
    int waitMillSec = 2800, seconds, milliseconds = 0;
    struct tm * ptm;

    now = time(NULL);
    ptm = gmtime ( &now );
    printf("time before: %d:%d:%d:%d\n",ptm->tm_hour,ptm->tm_min,ptm->tm_sec, milliseconds );

    /* wait until next full second */
    while(now == time(NULL));

    milli = clock();
    /* DO SOMETHING HERE */
    /* for testing wait a user define period */
    wait(waitMillSec);
    milli = clock() - milli;

    /*create timestamp with milliseconds precision */
    seconds = milli/CLOCKS_PER_SEC;
    milliseconds = milli%CLOCKS_PER_SEC;
    now = now + seconds;
    ptm = gmtime( &now );
    printf("time after: %d:%d:%d:%d\n",ptm->tm_hour,ptm->tm_min,ptm->tm_sec, milliseconds );
    return 0;
}

【问题讨论】:

    标签: c windows datetime time.h


    【解决方案1】:

    以下代码似乎可以提供毫秒级的粒度:

    #include <windows.h>
    #include <stdio.h>
    
    int main(void) {
        SYSTEMTIME t;
        GetSystemTime(&t); // or GetLocalTime(&t)
        printf("The system time is: %02d:%02d:%02d.%03d\n", 
            t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);
        return 0;
    }
    

    这是基于http://msdn.microsoft.com/en-us/library/windows/desktop/ms724950%28v=vs.85%29.aspx。以上代码 sn-p 在 Windows 7 上使用 CYGWIN 进行了测试。

    对于 Windows 8,有 GetSystemTimePreciseAsFileTime,它“以尽可能高的精度 (

    您最初的方法可能在 99.99% 的情况下都可以(忽略一个小错误,如下所述)。你的方法是:

    • 通过反复调用time() 直到值更改,等待下一秒开始。
    • 从time() 保存该值。
    • 保存来自clock()的值。
    • 使用clock() 的当前值和两个保存的值计算所有后续时间。

    您的小错误是前两个步骤颠倒了。

    但是即使这个固定,也不能保证 100% 工作,因为没有原子性。两个问题:

    • 您的代码循环 time() 直到您进入下一秒。但是你对它有多远?它可能是 1/2 秒,甚至是几秒(例如,如果您正在运行带有断点的调试器)。

    • 然后你打电话给clock()。但是这个保存的值必须“匹配”time() 的保存值。 如果这两个调用几乎是瞬时的,就像它们通常那样,那么这很好。但是 Windows(和 Linux)时间片,所以不能保证。

    另一个问题是clock 的粒度。如果 CLOCKS_PER_SEC 是 1000,就像您的系统上的情况一样,那么您当然可以做的最好的事情是 1 毫秒。但它可能比这更糟:在 Unix 系统上它通常是 15 毫秒。您可以通过将clock 替换为QueryPerformanceCounter(), 来改进这一点,就像timespec equivalent for windows 的答案一样,但考虑到前两个问题,这可能是多余的。

    【讨论】:

    • 非常感谢您的快速回复。当我回到我的工作机器时,我会试试这个。直到现在我都不敢使用任何 Windows 标头。不幸的是,我必须使用 Windows xp 和 Visual Studio 6.0,希望这不会是一个问题。
    • @morten:msdn 链接显示GetSystemTime 在 Windows 2000 及更高版本上可用,我刚刚验证它似乎可以在我的 XP Home SP3 机器上运行。祝你好运,告诉我们你最终做了什么。
    • 只是想说谢谢,我刚刚实现了你的想法,一切正常
    【解决方案2】:

    时钟周期完全不能保证以毫秒为单位。您需要将clock() 的输出显式转换为毫秒。

    t1 = clock();
    // do something
    t2 = clock();
    long millis = (t2 - t1) * (1000.0 / CLOCKS_PER_SEC);
    

    【讨论】:

      【解决方案3】:

      既然你在 Windows 上,为什么不直接使用Sleep()?

      【讨论】:

      • 遗憾的是我不知道。正如我所说,我对 c 编程很陌生,我花了很长时间才想出一个等待函数 :)
      • @morten - 繁忙的循环不必要地消耗大量 CPU。非零 Sleep() 将当前进程的时间片放弃给内核,以便它可以调度另一个进程运行。
      猜你喜欢
      • 1970-01-01
      • 2011-12-30
      • 2020-03-18
      • 1970-01-01
      • 2014-10-21
      • 2018-10-10
      • 2023-03-17
      • 2015-11-06
      • 2011-05-01
      相关资源
      最近更新 更多