1. 程式人生 > >C++14系列(2):C/C++的時間函數

C++14系列(2):C/C++的時間函數

復習 -a 執行時間 htm 結果 down pro addclass data-

C++筆記開始

為了好好研究下C++14。順便復習下曾經的C++知識。搞了個git(不斷完好中):
https://github.com/rododo/cpp14examples.git
裏面會慢慢封裝一些經常使用的函數。並做一些測試驗證。project是建立在Ubuntu的Eclipse之上,見系列(1)環境搭建。

經常使用的時間函數

參考:
http://blog.chinaunix.net/uid-24517893-id-363870.html

時間函數經常使用到的幾個概念:Calendar Time(日歷時間)。epoch(時間點),clock tick(時鐘計時單元)Coordinated Universal Time(UTC):世界標準時間,即格林威治標準時間(Greenwich Mean Time,GMT)。

epoch:時間點。

在標準C/C++中是一個整數,它用當前的時間和標準時間點的相差秒數來表示。它能夠理解成日歷時間,由於它已經是一個差值了。

日歷時間(Calendar Time),是用“從一個標準時間點到此時的時間經過的秒數”來表示的時間。

clock tick:時鐘計時單元。一個時鐘計時單元的時間長短是由CPU控制的。一個clock tick不是CPU的一個時鐘周期。而是C/C++的一個基本計時單位。

進程的CPU使用時間計時

C/C++中的cpu使用計時函數是clock(),而與其相關的數據類型是clock_t。這個函數返回從“開啟這個程序進程”到“程序中調用clock()函數”時之間的CPU時鐘計時單元(clock tick)數。當中clock_t是用來保存時間的數據類型。
clock_t是一個長整形數。在time.h文件裏,還定義了一個常量CLOCKS_PER_SEC,它用來表示一秒鐘會有多少個時鐘計時單元,例如以下打印的是進程執行至今占用的cpu時間秒數。而且它是算單核的秒數,假設這個程序是多線程的。core1和core2同一時候被某程序的兩個線程使用了5s的cpu執行時間片。那麽此時打印的應該是10s(已經驗證)。

printf("Elapsed time:%u secs.\n",clock()/CLOCKS_PER_SEC);

日歷時間

在C/C++中通過 < time.h > 裏的time函數獲得日歷時間。日歷時間(Calendar Time)是通過time_t數據類型來表示的。用time_t表示的時間(日歷時間)是從一個時間點(比如:1970年1月1日0時0分0秒)到此時的秒數。time_t實際上是長整型。


用time()函數結合其它函數(如:localtime、gmtime、asctime、ctime)能夠獲得當前系統時間或是標準時間。

time_t time(time_t * timer
);

日歷時間(秒)與日期(年月日)關系

在標準C/C++中。我們可通過tm結構來獲得日期。tm結構在time.h中有定義,相當於一個包括了年月日小時分鐘等的結構體。

ANSI C標準稱使用tm結構的這樣的時間表示為分解時間(broken-down time)。
而日歷時間(Calendar Time)是從一個時間點到此時的秒數,類型比較簡單。

在time.h頭文件裏,我們還能夠看到一些函數,它們都是以time_t為參數類型或返回值類型的函數:

double difftime(time_t time1, time_t time0);
time_t mktime(struct tm * timeptr);
time_t time(time_t * timer);
char * asctime(const struct tm * timeptr);
char * ctime(const time_t *timer);

此外。time.h還提供了兩種不同的函數將日歷時間(一個用time_t表示的整數)轉換為我們平時看到的把年月日時分秒分開顯示的時間格式tm:

struct tm * gmtime(const time_t *timer);                                          
struct tm * localtime(const time_t * timer);

固定的日期格式打印

使用函數:

char * asctime(const struct tm * timeptr);
char * ctime(const time_t *timer);

打印結果:
比如 Wed Jan 02 02:03:55 1980\n\0

當中asctime()函數是通過tm結構來生成字符串。所以能夠傳給世界時間或者本地時間,而ctime()是通過日歷時間來生成字符串。ctime()函數須要先參照本地的時間設置,把日歷時間轉化為本地時間,然後再生成格式化後的字符串。所以一般其打印的是本地時間字符串。

自己定義的日期格式打印

使用strftime()函數將時間格式化為想要的格式。它的原型例如以下:

size_t strftime(
   char *strDest,
   size_t maxsize,
   const char *format,
   const struct tm *timeptr 
);

樣例:

strftime(str,100,"It is now %I %p",ptr);
printf(str);

其執行結果為:
It is now 4PM
樣例:

strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime);
printf(tmpbuf);

執行結果:
Today is Saturday, day 30 of July in the year 2005.

分解時間轉化為日歷時間

分解時間,在C/C++中指tm結構。我們能夠使用mktime()函數將tm結構轉化為日歷時間。其函數原型例如以下:

time_t mktime(struct tm * timeptr);

< sys/time.h >的計時函數

除了上述的標準C/C++用到的時間函數外,Linux系統也提供了一個函數。能夠精確到微秒。

這就是gettimeofday函數,它獲得的時間精確到微秒(1e-6 s)量級。

在一段代碼前後分別使用例如以下:

struct timeval tv_begin, tv_end;
gettimeofday(&tv_begin, NULL);
foo();
gettimeofday(&tv_end, NULL);

結構體timeval的定義為:

struct timeval{
long int tv_sec; // 秒數
long int tv_usec; // 微秒數
}

time僅僅能返回秒級的返回值。而該結構體能精確到微秒級。
該函數和time函數一樣都是按真實世界的時間來計算的。

總結

本文介紹了C/C++中的有關日期和時間的概念,並通過各種實例講述了這些函數和數據結構的用法。

假設要測試優化的程序的執行效率,一般測量進程在cpu上使用的時間片之和,能夠用clock函數,clock函數並不代表真實世界的時間。

真實世界的時間則是time或者gettimeofday函數得到的。它們也能夠用於日期的顯示。

C++14系列(2):C/C++的時間函數