C语言中常用计时方法总结

📅 2026/7/28 2:22:23
C语言中常用计时方法总结
C语言中常用计时方法总结1. time()头文件time.h函数原型time_t time(time_t * timer)功能返回以格林尼治时间GMT为标准从1970年1月1日00:00:00到现在的此时此刻所经过的秒数。用time()函数结合其他函数如localtime、gmtime、asctime、ctime可以获得当前系统时间或是标准时间。用difftime函数可以计算两个time_t类型的时间的差值可以用于计时。用difftime(t2,t1)要比t2-t1更准确因为C标准中并没有规定time_t的单位一定是秒而difftime会根据机器进行转换更可靠。用法time_tstart,end;starttime(NULL);//or time(start);//…calculating…endtime(NULL);printf(time%d\n,difftime(end,start));总结C标准库中的函数可移植性最好性能也很稳定但精度太低只能精确到秒对于一般的事件计时还算够用而对运算时间的计时就明显不够用了。2. clock()头文件time.h函数原型clock_t clock(void);功能该函数返回值是硬件滴答数要换算成秒需要除以CLK_TCK或者 CLK_TCKCLOCKS_PER_SEC。比如在VC6.0下这两个量的值都是1000。用法clock_tstart,end;start clock();//…calculating…end clock();printf(time%f\n,(double)end-start)/CLK_TCK);总结可以精确到毫秒适合一般场合的使用。3. timeGetTime()WIN32API头文件Mmsystem.h 引用库 Winmm.lib函数原型DWORD timeGetTime(VOID);功能返回系统时间以毫秒为单位。系统时间是从系统启动到调用函数时所经过的毫秒数。注意这个值是32位的会在0到2^32之间循环约49.71天。用法DWORDstart,end;start timeGetTime();//…calculating…end timeGetTime();printf(time%d\n,end-start);总结该函数的时间精度是五毫秒或更大一些这取决于机器的性能。可用timeBeginPeriod和timeEndPeriod函数提高timeGetTime函数的精度。如果使用了连续调用timeGetTime函数一系列返回值的差异由timeBeginPeriod和timeEndPeriod决定。4. GetTickCount()WIN32API头文件windows.h函数原型DWORD WINAPI GetTickCount(void);功能返回自设备启动后的毫秒数不含系统暂停时间。用法DWORDstart,end;start GetTickCount();//…calculating…end GetTickCount();printf(time%d\n,end-start);总结精确到毫秒。对于一般的实时控制使用GetTickCount()函数就可以满足精度要求。5. QueryPerformanceCounter()、QueryPerformanceFrequency()WIN32API头文件windows.h函数原型BOOLQueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);BOOLQueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);功能前者获得的是CPU从开机以来执行的时钟周期数。后者用于获得你的机器一秒钟执行多少次就是你的时钟周期。补充LARGE_INTEGER既可以是一个8字节长的整型数也可以是两个4字节长的整型数的联合结构 其具体用法根据编译器是否支持64位而定typedefunion_LARGE_INTEGER {struct{ DWORD LowPart ; LONG HighPart; }; LONGLONG QuadPart ; }LARGE_INTEGER;用法在进行定时之前先调用QueryPerformanceFrequency()函数获得机器内部定时器的时钟频率然后在需要严格定时的事件发生之前和发生之后分别调用QueryPerformanceCounter()函数利用两次获得的计数之差及时钟频率计算出事件经历的精确时间。LARGE_INTEGERnum; longlong start,end,freq;QueryPerformanceFrequency(num); freqnum.QuadPart; QueryPerformanceCounter(num); startnum.QuadPart;//…calculating…QueryPerformanceCounter(num);endnum.QuadPart;printf(time%d\n,(end-start)*1000/freq);总结这种方法的定时误差不超过1微秒精度与CPU等机器配置有关一般认为精度为透微秒级。在Windows平台下进行高精度计时的时候可以考虑这种方法。6. gettimeofday()Linux C函数。头文件sys/time.h函数原型int gettimeofday(struct timeval *tv,struct timezone *tz);说明其参数tv是保存获取时间结果的结构体参数tz用于保存时区结果若不使用则传入NULL即可。timeval的定义为[cpp] view plain copy print?structtimeval {longtv_sec;// 秒数longtv_usec;//微秒数}可见该函数可用于在linux中获得微秒精度的时间。用法struct timevalstart,end;gettimeofday(start,NULL);//…calculating… gettimeofday(end,NULL);long timeuse 1000000 * (end.tv_sec -start.tv_sec ) end.tv_usec -start.tv_usec;printf(time%f\n,timeuse /1000000.0);总结使用这种方式计时精度可达微秒。经验证在armlinux的环境下此函数仍可使用。推荐。7. RDTSC - 读取时间标签计数器X86架构CPU汇编指令。操作码0F 31 指令RDTSC功能将时间标签计数器读入 EDX:EAX寄存器中。说明在Pentium以上的CPU中提供了一条机器指令RDTSC来读取这个时间戳的数字并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C语言保存函数返回值的寄存器所以我们可以把这条指令看成是一个普通的函数调用inlineunsignedlonglongGetCycleCount() { __asmRDTSC }如果编译器不允许直接用RDTSC的话可以用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31inlineunsignedlonglongGetCycleCount() { __asm_emit0x0F__asm_emit0x31}计算时还需要将得到的数字除以CPU的主频单位GHZ就能得到纳秒级的时间了。暂时我还没找到好的获得机器主频的方法Windows平台下可以考虑用QueryPerformanceFrequency()函数但这样一来就没办法在Linux下使用此方法。后来我考虑配合sleep函数获取1秒中的机器周期数的方法来得到CPU主频。如果哪位有更好的方法还请多多请教。#ifdef WIN32#include#else#include#endifinline unsigned long long GetNTime() { __asm(RDTSC); } static double hz0.0; void init_timer() { longlong t1GetNTime();#ifdef WIN32Sleep(1000);#elsesleep(1);#endiflonglong tGetNTime()-t1; hz(double)t/1000000000;printf(hz%fGhz\n,hz); } long long u_timer(long long*t,intmode) {if(hz0.001) init_timer();if(!mode) {*tGetNTime();return0; } longlong t1GetNTime()-*t; t1/hz; longlong nst100; longlong us(t1/1000)00; longlong ms(t1/1000000)00; longlongst1/1000000000;printf(time);if(s!0)printf(%llds,s);if(ms!0)printf(%lldms,ms);if(us!0)printf(%lldus,us);if(ns!0)printf(%lldns,ns);printf(\n);*tGetNTime(); returnt1; }总结这种方法精确到纳秒但缺点是非常短时间的计时会不稳定。最近因为项目需要我也找了一下ARMLinux平台上可以用的计时方法后来选择了gettimeofday()。不知道ARMLinux平台上有没有类似RDTSC的这种指令。