我正在尝试打印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中的算术。
答案 0 :(得分:9)
谁说time_t
是long
?它可以是任何算术类型。
使用时必须将其明确地转换为某些已定义的类型
printf
。
使用ostream
,并避免此类问题。
答案 1 :(得分:8)
我希望输出为
1_1389610399_2_3
你错了预料到这一点。不同类型具有不同的大小,当您通过varargs传递“错误”类型时,这意味着接收器无法再在预期位置找到堆栈中的所有内容。这就是当格式化代码与参数不匹配时行为未定义的原因:接收者没有读取调用者正在编写的相同类型。
您看到的0
打印出您预期的位置b
,是您传递时在堆栈上放置的64位long long
值的最重要的32位time_t
通过varargs(在此实现中)。 %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
打印每个组成部分。
答案 2 :(得分:2)
要以安全的方式显示其(time_t
)内容,您应首先使用(例如)gmtime
将其转换为struct tm
,然后使用其中一个字段或使用strftime
将其进一步转换为字符串。
答案 3 :(得分:1)
要使用格式字符串打印64位整数,您必须使用%I64d
而不是%ld
。
但是,因为time_t
的类型取决于硬件的位数,所以要洁具。
答案 4 :(得分:0)
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
希望有所帮助! 格尔茨, 迈克尔