Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何导致std::mktime失败?_C++_Gcc_64 Bit - Fatal编程技术网

C++ 如何导致std::mktime失败?

C++ 如何导致std::mktime失败?,c++,gcc,64-bit,C++,Gcc,64 Bit,我过去常常在程序中设置/获取时间。手册页显示: 允许时间值超出其正常范围 如果不能将结果表示为std::time\t,则返回-1 我在我的单元测试中尝试了所有的方法使这个函数失败,但是没有成功。 只是一些尝试: #include <iostream> #include <iomanip> #include <ctime> #include <stdlib.h> int main() { setenv("TZ", "/usr/share/z

我过去常常在程序中设置/获取时间。手册页显示:

允许时间值超出其正常范围

如果不能将结果表示为std::time\t,则返回-1

我在我的单元测试中尝试了所有的方法使这个函数失败,但是没有成功。 只是一些尝试:

#include <iostream>
#include <iomanip>
#include <ctime>
#include <stdlib.h>

int main()
{
    setenv("TZ", "/usr/share/zoneinfo/America/New_York", 1); // POSIX-specific

    std::time_t t = std::time(nullptr);
    std::tm tm = *std::localtime(&t);
    std::cout << "Today is           " << std::put_time(&tm, "%c %Z")
              << " and DST is " << (tm.tm_isdst ? "in effect" : "not in effect") << '\n';
    tm.tm_year = 550;
    tm.tm_year = 123456789;
    tm.tm_mon = 88;
    tm.tm_mday = 200;
    //tm.tm_mon -= 100;  // tm_mon is now outside its normal range
    std::mktime(&tm);  // tm_dst is not set to -1; today's DST status is used
    std::cout << "100 months ago was " << std::put_time(&tm, "%c %Z")
              << " and DST was " << (tm.tm_isdst ? "in effect" : "not in effect") << '\n';
}

对于建议的输入
std::numeric\u limits::max()
,您的示例确实失败。您的示例没有检查-1返回值。如果你加上

auto err = std::mktime(&tm);  // tm_dst is not set to -1, err is.
对于此输入,
err
设置为-1

你可以在下面看到失败

您还可以在以下位置看到失败:

两种服务上的输出相同:

Today is           Thu Apr 19 09:07:40 2018 EDT and DST is in effect
100 months ago was Thu ? 200 09:07:40 -2147481749 EDT and DST was in effect
-1

当发生溢出时,
mktime
将无法更新
tm
结构,例如,当年份设置为
INT\u MAX
并且添加了超过12个月(超过一年)时。像这样:

std::tm tm;
tm.tm_year = INT_MAX;
tm.tm_mon = 13;
std::time_t rc = std::mktime(&tm);
如果您将年份设置为
INT\u MIN
,月份设置为零并减去一天(将
tm\u mon
设置为0,将
tm\u mday
设置为-1),则它也将无法更新
tm
结构:

如果月份和tm_mday的组合仍然少于一年,则当year设置为
INT_MAX
时,它不会失败,因为这仍然是可表示的


然而,正如MSalters提到的,这并不总是导致返回值为-1。有时,
mktime
无法将时间戳规范化为有效的
tm
结构时,它将返回-1。但是,根据实现的不同,
mktime
也只能在时间不能用
time\t
表示时返回-1(因为time\t是“未指定的”)。在后一种情况下,假设tm结构规范化为有效值实际上是危险的。

如果您将年份更改为例如
INT\u MAX
std::mktime
将返回-1。从现在开始已经很长时间了,但是你现在用的日期作为例子仍然可以表示…@Elijan9谢谢,但这并没有让它失败。检查编辑。如果失败返回-1,那么它确实会打印负值。你说失败是什么意思?@B确切地说,你需要检查返回值,当
mktime
无法设置有效时间时(例如,当它溢出时),返回值将为-1@Elijan9:这很重要,因为即使在
INT\u MAX
为32位的系统上,
time\u t
也可以合理地为64位。由于一年中的时间远远少于2^32秒,因此任何32位的年份都可以转换为64位的时间(以秒为单位)。我进行检查(请参见编辑中的示例)。为什么它能在ideone上工作,而不能在coliru上工作,以及在我的编译器上工作?@Bцћcoliru在给定的示例中也会失败;您不能假设某个特定的实现。一个实现可以很好地使用64位进行所有后台计算,并在任何操作之前将
tm_year
转换为64位。我刚刚构建并安装了一个32位gcc编译器,当我使用INT_MAX时它会失败。但是64位,我不能让它失败。它永远不会回来-1@MSalters从技术上讲,它将失败,因为标准将tm_year定义为
int
,而int_MAX是数据类型可以保存的最大值?(但是,mktime可能不会注意到溢出。)
Today is           Thu Apr 19 09:07:40 2018 EDT and DST is in effect
100 months ago was Thu ? 200 09:07:40 -2147481749 EDT and DST was in effect
-1
std::tm tm;
tm.tm_year = INT_MAX;
tm.tm_mon = 13;
std::time_t rc = std::mktime(&tm);
std::tm tm;
tm.tm_year = INT_MIN;
tm.tm_mon = 0;
tm.tm_mday = -1;

std::time_t rc = std::mktime(&tm);