0

我知道 size_t 是无符号的,因此不允许使用负值,据我所知,time_t 是有符号的,因此我可以将 -1 分配给 size_t。但是,对于 time_t 我并不完全确定。如果我通过头文件遵循定义,我会在这里结束:

typedef __time_t time_t;

,然后在这里:

__STD_TYPE __TIME_T_TYPE __time_t;  /* Seconds since the Epoch.  */

最后

#define __TIME_T_TYPE       __SYSCALL_SLONG_TYPE

我不太确定__SYSCALL_SLONG_TYPE是什么,但我猜它是有符号的 long。不幸的是,即使做了这个跟踪,我也只能希望其他 c++11 平台也有相同的实现。我仍然不确定这对所有人来说都是合法的和明确的:

size_t foo = -1;

当然,对 time_t 进行签名是有意义的,因为可以有负时间偏移,例如对时区建模。但另一方面,让它无符号是有意义的,因为在 1970 年之后还有很多秒要计算。所以常识是双向的 :) 在 time_t 上谷歌搜索返回了这个:

“由于历史原因,它通常实现为一个整数值,表示自 UTC 1970 年 1 月 1 日 00:00 小时以来经过的秒数(即 unix 时间戳)。尽管图书馆可以使用替代时间表示来实现这种类型。”

来源:http ://www.cplusplus.com/reference/ctime/time_t/

并在同一页上:“可移植程序不应直接使用这种类型的值,而应始终依赖对标准库元素的调用将它们转换为可移植类型。”

所以 time_t 在所有系统上都没有明确定义,但是 time() 返回一个 time_t: 所以我不会是第一个在接口中导出它的人。我应该使用什么其他类型?

我问这两个原因:

  • 速度:使用结构体,如struct tm很慢,因为它有更多字节,因此复制它或将其与另一个 struct tm 进行比较将比使用 long 慢。
  • 排序:我想要一个快速的日期数据类型,它允许我执行 a < b 来确定日期 a 和 b 中的哪一个在前。

问题:由于 time_t 不是所有平台上定义明确的时间表示,我可以使用哪种 (1) 快速和 (2) 可比较的数据类型是可移植的?

例如,关于 time_t 的排序:

#include <iostream>
#include <ctime>
#include <cstring>

int main() {
    struct tm tm_a, tm_b;
    memset(&tm_a, 0, sizeof(struct tm));
    memset(&tm_b, 0, sizeof(struct tm));
    if(strptime("2014-01-01 12:00:00", "%Y-%m-%d %H:%M:%s", &tm_a) && strptime("2014-01-01 11:59:59", "%Y-%m-%d %H:%M:%s", &tm_b)) {
        if(mktime(&tm_a) > mktime(&tm_b)) std::cout << "time_t ordering OK." << std::endl;
        else std::cout << "time_t ordering tainted" << std::endl;
    } else std::cout << "failed to parse time" << std::endl;
    return 0;
}

time_t在所有平台上都不会受到污染吗?

4

3 回答 3

4

(time_t)(-1)已经意味着“这不是一个有效的时间”,不管time_t实际上是什么。标准函数mktime在出错时返回这个值,你也可以。

C 和 C++ 标准没有说明time_t. 标准函数difftime计算时间差(以秒为单位),double表示为 的两次时间之间的时间差,这是按时间顺序排列值time_t的唯一方法。time_t但是,POSIX 标准指定它time_t是以秒为单位的时间,因此在 POSIX 系统上可以time_t直接与<.

请注意,C 和 POSIX 都允许time_t是任何算术类型(不仅仅是整数)。

于 2014-06-14T12:16:58.307 回答
1

如果您需要保证在不同平台之间可移植的时间表示,您需要使用或创建一个库来处理您使用的平台之间的差异。

例如Boost.Date_Time,您可以在那里选择它支持的任何表示。您甚至可以以独立于平台的方式使用自纪元以来经过的秒数(在 boost 支持的所有平台上)。

于 2014-06-14T12:28:28.783 回答
0

我已经沉迷于optional(通过 boost,或者基于 C++1y tr 工作论文推出你自己的)。

optional<foo>是 afoo或 a nullopt。您访问foovia dereerence,但数据存储在optionalvia 联合中。我的懒惰实现使用一个指针来表示“它是foo不是”,因为这使得调试变得微不足道。

它既比标志值更能传达故障,又替换了我编写的代码中的一堆基于指针的标志。

于 2014-06-14T16:50:26.227 回答