2014-01-13 66 views
6

我試圖打印time_t而不只是在Microsoft Visual Studio項目中詮釋它,它給我意想不到的結果。源代碼是打印time_t長整型沒有鑄造給出了意想不到的行爲

#include <time.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/timeb.h> 
#include <string.h> 

int main() 
{ 
    int a=1,b=2; 
    long int c=3; 
    time_t myTime; 
    time(&myTime); 
    printf("%d_%ld_%d_%ld",a,myTime,b,c); 
    printf("\n"); 
    getchar(); 
    return 0; 
} 

輸出是1_1389610399_0_2。這在我的linux機器上運行良好。我明白,time_t不應該打印這樣,但我不知道爲什麼?請告訴我如何調試這樣的問題?

編輯:我期待的輸出爲1_1389610399_2_3給誰說time_tlong的事實,time_t在C.

+0

我不明白你在問什麼。你知道你打印錯誤,但不知道爲什麼它不符合你的期望?你想要什麼輸出? – BoBTFish

+0

C中的time_t類型被認爲是算術類型。所以,預期的輸出應該是類似於1_1389610399_2_3。我不明白爲什麼產量會以即將到來的方式出現。 – Abhishek

+2

@Abhishek:從結果看(我沒有檢查過文檔),'time_t'在Windows上是'long long',這很明智。當你將錯誤類型作爲可變參數傳遞時,事情就會出錯。 –

回答

8

我期待的輸出爲1_1389610399_2_3

你錯了,期待這一點。不同的類型具有不同的大小,並且當您通過可變參數傳遞「錯誤」類型時,這意味着接收器無法在預期位置找到堆棧中的所有內容。這就是爲什麼格式化代碼與參數不匹配時行爲未定義的原因:接收方不讀取與調用方寫入的類型相同的類型。

0,你看到打印出來,你預期b,是64位long long值的最顯著32位,它被放置在堆棧上時,通過可變參數傳遞time_t(在該實現)。 %ld格式代碼僅佔用myTime值的前4個字節,剩下的部分將由下一個格式化代碼執行。

當它在linux上工作時,這是因爲time_tlong在該實現上,因此您的格式代碼與您傳遞的類型相匹配。

有一種「多用途」的方式來打印任何有符號整數,即將其轉換爲intmax_t並使用格式代碼%j。很抱歉,您不能保證time_t是一種有符號類型,或者甚至是整數類型。因此,這將是便攜式,但仍然不嚴格,因爲myTime理論上的值可能根本不在intmax_t的範圍內。在C++中,你應該使用std::cout << myTime;,因爲這樣可以避免你需要知道time_t的實際類型(只要它不是任何種類的char)。

或者,您可以使用difftime強制您的時間爲double,您知道如何打印。或者,您可以使用gmtimelocaltime獲取分解的日曆時間,其中每個組件都知道如何使用printfstrftime進行打印。

+0

感謝您的詳細解答@steve,但不應該按照這個邏輯,printf(「%d_%ld_%d」,a,b,c);應該給出輸出爲1_2_0,而是給出輸出爲1_2_3。 – Abhishek

+0

@Ahhishek:沒有。 Windows上的「int」和「long」大小相同。當然,它仍然是未定義的行爲。 –

9

視爲算術?它可以是任何算術類型。 使用 printf時,您必須明確地將其轉換爲某種定義的類型。

使用ostream,並避免這樣的問題。

+1

但是我怎麼不會影響後續的b參數呢?我不明白這一點。 – Abhishek

+1

@Abhishek因爲你將錯誤的類型傳遞給var_args。這會導致var args機制與您的輸入不同步。 (通常的機制是將提取的元素的大小添加到char *中以獲取下一個元素的地址)。您必須將接收程序期望的確切類型傳遞給var args。 –

+0

謝謝@詹姆斯,現在很清楚。我將更多地關注printf實現和var args機制以獲得更多洞察。 – Abhishek

2

,來顯示自己(time_t)內容以安全的方式,你應該首先使用(即)gmtime將其轉換爲struct tm,然後用它的一個字段或使用strftime將其進一步轉換爲字符串。

0

time()函數返回「自UTC從1970年1月1日00:00開始」過去的秒數。

來源:http://en.cppreference.com/w/c/chrono/time_t

所以,你得到的值(1389610399)是相當優良的,因爲它是:

60分之1389610399(=分鐘)/ 60(=小時)/ 24(=天)/ 365〜44年,這似乎很合理。

因此,例如,如果要獲取天數,則將時間值除以3600. 如果要獲取日期,請參閱其他函數,如localtime()或gmtime( ) - 後者以UTC形式返回日期和時間。看到提供的例子: http://en.cppreference.com/w/c/chrono/gmtime

希望幫助! Greetz, Michael

1

要使用格式字符串打印64位整數,您必須使用%I64d而不是%ld。 但是,由於time_t的類型取決於硬件的位數,因此請謹慎使用。

相關問題