[英]Printing time_t as long int without casting gives unexpected behaviour
我試圖打印time_t而不在Microsoft Visual Studio Project中將其作為long int投射,它給了我意想不到的結果。 源代碼是
#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_t
被認為是C中的算術。
誰說time_t
很long
? 它可以是任何算術類型。 使用printf
時,必須將其顯式轉換為某些已定義的類型。
使用ostream
,並避免此類問題。
我期待輸出為
1_1389610399_2_3
你錯的期待這個。 不同類型具有不同的大小,當您通過varargs傳遞“錯誤”類型時,這意味着接收器無法再在預期位置找到堆棧中的所有內容。 這就是當格式化代碼與參數不匹配時行為未定義的原因:接收者沒有讀取調用者正在編寫的相同類型。
您看到的0
打印出您預期的位置b
,是通過varargs傳遞time_t
時在堆棧中放置的64位long long
值的最重要的32位(在此實現中)。 %ld
格式化代碼僅占用myTime
值的前4個字節,剩下的將由下一個格式化代碼占用。
當它適用於linux時,那是因為time_t
在該實現上很long
,因此您的格式代碼與您傳遞的類型相匹配。
有一種“通用”方式來打印任何有符號整數,即將其轉換為intmax_t
並使用格式代碼%j
。 遺憾的是,您無法保證time_t
是帶符號的類型,甚至不是整數類型。 因此,這將更加便攜,但仍然不是那么嚴格,因為理論上 myTime
的值可能根本不在intmax_t
范圍內。 在C ++中你應該使用std::cout << myTime;
,因為這可以避免你需要知道time_t
的實際類型別名(只要它不是任何類型的char
)。
或者,你可以使用difftime
來強制你double
的時間,你知道如何打印。 或者您可以使用gmtime
或localtime
來獲取一個細分的日歷時間,您知道如何使用printf
或strftime
打印每個組件。
要以安全的方式顯示其( time_t
)內容,您應首先使用(即。) gmtime
將其轉換為struct tm
,然后使用其中一個字段或使用strftime
將其進一步轉換為字符串。
要使用格式字符串打印64位整數,您必須使用%I64d
而不是%ld
。 但是,因為time_t
的類型取決於硬件的位數,所以要有用。
time()函數返回“自UTC時間1970年1月1日00:00起”所經過的秒數。
資料來源: http : //en.cppreference.com/w/c/chrono/time_t
所以,你得到的價值(1389610399)非常好,因為它是:
1389610399/60(=分鍾)/ 60(=小時)/ 24(=天)/ 365〜44年,這似乎很合理。
因此,如果您想獲得天數,例如,則將時間值除以3600.如果您想獲取日期,請參考其他函數,例如localtime()或gmtime() - 后者返回UTC中的日期和時間。 請參閱http://en.cppreference.com/w/c/chrono/gmtime上提供的示例
希望有所幫助! 格雷茨,邁克爾
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.