将time_t打印为long int而不进行强制转换会产生意外行为

Abh*_*hek 6 c c++ datetime

我试图打印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;
}
Run Code Online (Sandbox Code Playgroud)

输出是1_1389610399_0_2.这在我的linux机器上运行正常.我知道time_t不应该像这样打印但是我不确定为什么?请告诉我如何调试这样的问题?

编辑:我期待输出被1_1389610399_2_3认为time_t是C中的算术.

Jam*_*nze 9

谁说time_t是一个long?它可以是任何算术类型.使用时必须将其明确地转换为某些已定义的类型 printf.

使用ostream,并避免此类问题.


Ste*_*sop 8

我期待输出 1_1389610399_2_3

你错的期待这个.不同类型具有不同的大小,当您通过varargs传递"错误"类型时,这意味着接收器无法再在预期位置找到堆栈中的所有内容.这就是当格式化代码与参数不匹配时行为未定义的原因:接收者没有读取调用者正在编写的相同类型.

0其中预期你,你看到打印出来b,是64位的最显著32位long long时传递一个值,该值被放置在栈上time_t通过可变参数(在该实现).该%ld格式的代码只用了前4个字节的值myTime,留下其余的将要采取的下一个格式代码.

当它工作在Linux上,这是因为time_tlong上实现,因此您的格式代码匹配你传递的类型.

有一种"通用"方式来打印任何有符号整数,即将其转换intmax_t为格式代码并使用格式代码%j.不幸的是,你不能保证它time_t是一个有符号的类型,或者它是一个整数类型.因此,这将更加便携,但仍然不是严格如此,因为myTime 理论上的价值可能根本不在范围内intmax_t.在C++中你应该使用std::cout << myTime;,因为这可以避免你需要知道别名的实际类型time_t(只要它不是任何类型char).

或者,您可以difftime用来强制您double知道如何打印的时间.或者您可以使用gmtimelocaltime获取一个细分的日历时间,每个组件都知道如何打印printf或使用strftime.