1. 程式人生 > >C語言計時函式

C語言計時函式

time()函式與time_t型別

標頭檔案:time.h

函式簽名time_t time( time_t *arg )

說明:返回當前計算機紀元時間,並將其儲存在arg指向的time_t型別中。所以可以time_t result = time(NULL),也可以time(&result)

計算機紀元時間:C語言和Unix創造並誕生於1970年,所以計算機以1970年1月1日作為紀元開始時間。

C語言標準並沒有指定time_t型別的編碼方式,但大多數遵循POSIX標準系統的time_t一般是32位有符號整數實現,以秒為最小單位,從1970年1月1日開始計數,所以能表示到2038年。

VS2017中有如下定義:

#ifndef _CRT_NO_TIME_T
    #ifdef _USE_32BIT_TIME_T
        typedef __time32_t time_t;
    #else
        typedef __time64_t time_t;
    #endif
#endif

...
#ifdef _USE_32BIT_TIME_T
    ...
        static __inline time_t __CRTDECL time(
        _Out_opt_ time_t* const _Time
        )
    {
        return
_time32(_Time); } ... #else ... static __inline time_t __CRTDECL time( _Out_opt_ time_t* const _Time ) { return _time64(_Time); } ... #endif

因為time_t型別編碼不能確定,所以儘量不要用t1-t2方式計算兩個time_t之間的時間間隔,而應該用double difftime( time_t time_end, time_t time_beg );

函式計算時間間隔。

擴充套件time_t表示計算機紀元時間,struct tm表示標準日曆時間。

struct tm定義如下:

struct tm
{
    int tm_sec;   // seconds after the minute - [0, 60] including leap second
    int tm_min;   // minutes after the hour - [0, 59]
    int tm_hour;  // hours since midnight - [0, 23]
    int tm_mday;  // day of the month - [1, 31]
    int tm_mon;   // months since January - [0, 11]
    int tm_year;  // years since 1900
    int tm_wday;  // days since Sunday - [0, 6]
    int tm_yday;  // days since January 1 - [0, 365]
    int tm_isdst; // daylight savings time flag
};

time_t可以和struct tm格式的時間進行互相轉換:

  • struct tm *gmtime( const time_t *time ):從time_t轉成struct tm,但該函式C11標準中才定義的。
  • time_t mktime( struct tm *time ):從struct tm轉成time_t

示例

    time_t start, end;
    start = time(NULL);
    _sleep(1000);
    end = time(NULL);
    printf("start time: %s\n", ctime(&start));
    printf("end time: %s\n", ctime(&end));
    printf("duration: %lf\n", difftime(end, start));

執行結果:

start time: Fri Jul 28 09:48:25 2017

end time: Fri Jul 28 09:48:26 2017

duration: 1.000000

總結:C標準庫中的函式,可移植性最好,效能也很穩定,但精度太低,只能精確到秒,對於一般的事件計時還算夠用,而對運算時間的計時就明顯不夠用了。

clock()函式與clock_t型別

標頭檔案:time.h

函式簽名clock_t clock(void)

說明:該函式返回值是硬體滴答數(未加工的程式啟動時開始經過的處理器時間),只有計算呼叫兩次clock的返回值才有意義,要換算成秒,需要除以CLOCKS_PER_SEC(每秒中的滴答數),VC中定義如下:

#define CLOCKS_PER_SEC  ((clock_t)1000)

當CPU被多個程序共享,clock返回值可能慢於真實時鐘,而如果一個程序內有多個執行緒或者多核處理,clock返回值可能快於真實時鐘。

注意:在32位機器上clock_t為32bit,所以clock_t在2147483648(2147秒或36分)後會回滾(即小於零)。

示例

示例1

    clock_t start, end;
    start = clock();
    _sleep(1234);
    end = clock();
    double duration = ((double)end - start) / CLOCKS_PER_SEC;
    printf("%f second", duration);

執行結果:

1.234000 second

示例二:

    clock_t start, end;
    start = clock();
    _sleep(1234);
    end = clock();
    int duration = end - start;
    printf("%d millisecond", duration);

執行結果:

1234 millisecond

總結:可以精確到毫秒,適合一般場合的使用。

timespec_get()函式與timespec型別

標頭檔案:time.h

函式簽名int timespec_get( struct timespec *ts, int base) (since C11)

說明:以base為基底,將當前計算機紀元時間填充到ts地址中。

timespec結構體定義如下:

    struct timespec
    {
        time_t tv_sec;  // Seconds - >= 0
        long   tv_nsec; // Nanoseconds - [0, 999999999]
    };

timespec精度是納秒級。

C11標準中定義TIME_UTC為通用協調時間,並推薦使用TIME_UTC作為base基底。

示例

    struct timespec start, end;
    timespec_get(&start, TIME_UTC);
    _sleep(1234);
    timespec_get(&end, TIME_UTC);

    char buffer[128];
    strftime(buffer, sizeof(buffer), "%Y/%m/%d %T", gmtime(&start.tv_sec));
    printf("start time: %s.%ld\n", buffer, start.tv_nsec);
    strftime(buffer, sizeof(buffer), "%Y/%m/%d %T", gmtime(&end.tv_sec));
    printf("end time: %s.%ld\n", buffer, end.tv_nsec);

    time_t d_sec = end.tv_sec - start.tv_sec;
    long d_nsec = end.tv_nsec - start.tv_nsec;
    long duration = d_sec*1E9 + d_nsec;
    printf("duration: %ld nanosecond\n", duration);

執行結果:

start time: 2017/07/28 04:34:26.577550200
end time: 2017/07/28 04:34:27.811685800
duration: 1234135600 nanosecond

總結:C11標準庫函式,跨平臺特性好,精度能達到納秒級,但是需要編譯器支援C11。

以上是C語言標準庫提供的函式,跨平臺特性較好,下面的幾個是特定平臺的API,所以視情況使用。

timeGetTime()函式

標頭檔案:timeapi.h(Windows.h中已經包括該標頭檔案)

函式簽名DWORD timeGetTime(void)

:Winmm.lib;Dll:Winmm.dll

說明:返回系統時間,以毫秒為單位。

timeGetTime函式返回值是一個DWORD(32bit),會在0到232之間迴圈,大約49.71天。如果使用這個返回值作為控制語句的條件可能會出現問題,所以建議使用這個函式計算兩個時間點之間的間隔。

timeGetTime函式的預設精度可以達到5毫秒或者更多,這個精度依賴於機器。可以使用timeBeginPeriod和timeEndPeriod函式增加timeGetTime的精度。timeGetTime返回的兩個連續值之間的最小間隔可以和timeBeginPeriod和timeEndPeriod設定的最小週期一樣大。

timeGetTime以DWORD儲存時間

timeGetSystemTime以MMTIME結構體儲存時間

示例

示例一:

#include<Windows.h>
#pragma comment(lib,"Winmm.lib")
int main() {
    DWORD start, end;
    start = timeGetTime();
    Sleep(1234);
    end = timeGetTime();
    printf("%d\n", end - start);
}

執行結果:

1235

示例二:

#include<Windows.h>
#pragma comment(lib,"Winmm.lib")
int main() {
    DWORD start, end;
    timeBeginPeriod(1);
    start = timeGetTime();
    Sleep(1234);
    end = timeGetTime();
    timeEndPeriod(1);
    printf("%d\n", end - start);
}

執行結果:

1234

GetTickCount函式

標頭檔案:Winbase.h(Windows.h中已經包括該標頭檔案)

函式簽名:DWORD WINAPI GetTickCount(void);

:Kernel32.lib;Dll:Kernel32.dll

說明:返回系統啟動後的時間,單位為毫秒。

GetTickCount功能只限於系統定時器,精度在10毫秒到16毫秒之間。GetTickCount的精度不受GetSystemTimeAdjustment函式影響。

該函式以DWORD(32bit)儲存時間,如果系統連續執行49.7天,將會迴圈到0,為避免這個影響,建議使用GetTickCount64函式

示例

#include<Windows.h>

int main() {
    DWORD start, end;
    start = GetTickCount();
    Sleep(1234);
    end = GetTickCount();
    printf("%d\n", end - start);
}

執行結果:

1234

QueryPerformanceCounter()、QueryPerformanceFrequency()高精度時間

標頭檔案:Winbase.h (Windows.h中已經包括該標頭檔案)

函式簽名

  • BOOL WINAPI QueryPerformanceCounter(
    _Out_ LARGE_INTEGER *lpPerformanceCount
    );
  • BOOL WINAPI QueryPerformanceFrequency(
    _Out_ LARGE_INTEGER *lpFrequency
    );

:Kernel32.lib;Dll:Kernel32.dll

說明:QueryPerformanceFrequency獲取CPU時鐘頻率;QueryPerformanceCounter獲取CPU時鐘計數器的當前值。通過這兩個函式可以計算兩點之間的時間間隔,精度為微妙級別。

LARGE_INTEGER定義如下:

typedef union _LARGE_INTEGER {
    struct {
        DWORD LowPart;
        LONG HighPart;
    } DUMMYSTRUCTNAME;
    struct {
        DWORD LowPart;
        LONG HighPart;
    } u;
    LONGLONG QuadPart;
} LARGE_INTEGER;

示例

#include<Windows.h>

DWORD64 ObtainCurrentTime() {
    LARGE_INTEGER num;
    QueryPerformanceCounter(&num);
    return num.QuadPart;
}

DOUBLE ComputeDuration(DWORD64 end, DWORD64 start) {
    LARGE_INTEGER frequency;
    QueryPerformanceFrequency(&frequency);
    return (DOUBLE)(end - start) / frequency.QuadPart;
}

int main() {
    DWORD64 start, end;
    start = ObtainCurrentTime();
    Sleep(1234);
    end = ObtainCurrentTime();
    DOUBLE duration = ComputeDuration(end, start);
    printf("%lf microsecond", duration);
}

執行結果:

1.234634 microsecond

相關推薦

C語言計時函式

time()函式與time_t型別 標頭檔案:time.h 函式簽名:time_t time( time_t *arg ) 說明:返回當前計算機紀元時間,並將其儲存在arg指向的time_t型別中。所以可以time_t result = time(NULL

C語言計時函式clock()

C語言clock()函式實現計時功能       函式clock()返回值為clock_t型別(一個長整型數),它的實際意義是指“程序啟動到呼叫clock()函式經過了多少個CPU時鐘計時單元”,藉助

C語言 trim函式實現

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> //去除尾部空格 char *rtrim(char *str) { if(str == N

C語言函式宣告、形參、實參

函式原型: 原型prototype是函式的宣告;描述了函式的返回值與引數;  函式原型說明了兩點: 1、該函式的返回值 2、該函式的引數及其型別 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 函式的引數: 引數到底是什

C語言isalpha函式

看程式碼: #include<ctype.h> #include<stdio.h> #include <iostream> using namespace std; int main(void){ char ch; int tot

c 語言函式遞迴來實現求 k 的 n 次方

       如果求取k的n次方,既可以用普通的方法實現,也可以用函式的遞迴來實現。        函式的遞迴即是自己呼叫自己的函式應用形式,即在main函式下定義一個函式,然後在這個函式內自己為了實現某個目的,函式

C語言探究函式遞迴的巧妙之處(以斐波那契數列為例)

對於許多C語言的初學者來說,函式是一個比較重要的版塊.函式的使用不僅在學習程式設計的時期可以方便我們解決一些問題.它在未來的工作中也是程式設計師們經常運用的東西.而函式的遞迴是函式這一版塊比較難懂的東西.因此小編以輸出斐波那契數列的第N項為例,來探討函式的遞迴的應用給我們的程式碼帶來的方便.

C語言 strrev函式

標頭檔案:#include<string.h> strrev()函式將字串逆置,其原型為: char *strrev(char *str); 【引數說明】str為要逆置的字串。 strrev()將str所指的字串逆置。 【返回值】返回指向逆置後的字串的指標。 strr

C語言函式(侵刪)

1.strlen 標頭檔案:#include <string.h> strlen()函式用來計算字串的長度,其原型為:unsigned int strlen (char *s);  s為指定的字串 #include<stdio.h> #include<

C語言assert函式完全攻略

斷言assert函式,C語言assert函式完全攻略 對於斷言,相信大家都不陌生,大多數程式語言也都有斷言這一特性。簡單地講,斷言就是對某種假設條件進行檢查。在 C 語言中,斷言被定義為巨集的形式(assert(expression)),而不是函式,其原型定義在<assert.h>檔

C語言read函式的那些坑

  今天在複習UNIX檔案系統,用到那個read函式,但是無意中卻掉到一個坑裡了,用了一個多小時才找到問題根源,這裡記錄一下。   問題是這樣的:我需要使用read和write函式把鍵盤輸入的資訊複製到輸出。所以我寫了如下程式: #include<stdio.h> #define MAX

linux下的c語言系統函式呼叫

目錄 4.linux下的系統函式的使用 c語言 4.1數學函式的使用 1pow函式 2.exp函式 3.log函式 4.rand()隨機數函式 4.2字元函式的使用 4.3系統時間與日期函式的使用 系統時間 時間間隔 4.4環境控制函式 &nb

Mr.J--C語言函式的建立(附嚴薇敏《資料結構》線性表程式碼)

  如何正確編寫 C 語言標頭檔案和與之相關聯的 c 源程式檔案 檢視此文章需要有一定的C語言程式設計基礎 首先就要了解它們的各自功能。要理解C 檔案與標頭檔案(即.h)有什麼 不同之處,首先需要弄明白編譯器的工作過程。 一般說來編譯器會做以下幾個過程: 1.預處理階段 2

C語言隨機函式的使用

rand()和srand()應該是初學者最先接觸到的隨機函數了,今天博主就這兩個函式陳述一下自己的理解。 這兩個函式的使用規範如下: /*這是一個模擬擲色子1800次的程式*/ #include <stdlib.h>

C語言函式指標陣列的初始化和使用

不比多說上一個程式碼,就懂了! 程式碼一: #include <stdio.h> int func(int i) {     printf("%d\n",i);     return i*i; } int

C語言malloc()函式與calloc()函式的區別

推薦部落格: 推薦部落格:https://blog.csdn.net/ddcodingya/article/details/80452397   推薦部落格:https:https://blog.csdn.net/Hackbuteer1/article/d

C語言 socket函式的簡單運用 29

下面所講的是在Linux系統上用gcc編寫的,Windows好像不能用。 socket是套接字,是用來在網路之間進行資料傳遞的。 在網路中,我們通過一個IP來確定一臺主機,再通過一個port來確定一個進行,而socket就是一個進行。因此:socket = IP + port   網路傳輸的

Linux : C語言pause()函式:讓程序暫停直到訊號出現

C語言pause()函式:讓程序暫停直到訊號出現   相關函式:kill, signal, sleep 標頭檔案:#include <unistd.h> 定義函式:int

c語言輸入函式getchar&fgets&scanf&scanf_s

//a)getchar:在鍵盤上輸入一個ASCII碼的文字,返回值得到的是一個數值, //c=getchar等價於scanf("%c",&c);在第一次執行時時阻塞,並等待輸入。 //如果下一次輸入緩衝中有剩餘還未提取的輸入資料,將不阻塞直接提取那些剩餘的資料; //b)fflush(std

C語言函式中引數的傳值與傳地址

任務程式碼: #include <stdio.h> void swap(int *a ,int *b)//按之前對指標認識,*a代表指標變數a,a儲存的是地址,*a是地址的值。 { //但是可以看到下面傳輸過程中swap(