簡體   English   中英

將time_t打印為long int而不進行強制轉換會產生意外行為

[英]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_tlong 它可以是任何算術類型。 使用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的時間,你知道如何打印。 或者您可以使用gmtimelocaltime來獲取一個細分的日歷時間,您知道如何使用printfstrftime打印每個組件。

要以安全的方式顯示其( 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM