我对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;
}
答案 0 :(得分:6)
以下代码似乎可能提供毫秒级别的粒度:
#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。上面的代码片段在Windows 7上使用CYGWIN进行了测试。
对于Windows 8,有GetSystemTimePreciseAsFileTime,它“以尽可能高的精度(<1us)检索当前系统日期和时间。”
你原来的方法可能会在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的答案一样,但考虑到前两个问题,这可能是非常的。
答案 1 :(得分:1)
时钟周期完全不保证以毫秒为单位。您需要将clock()的输出显式转换为毫秒。
t1 = clock();
// do something
t2 = clock();
long millis = (t2 - t1) * (1000.0 / CLOCKS_PER_SEC);
答案 2 :(得分:0)
由于您使用的是Windows,为什么不使用Sleep()?