【问题标题】:Why does `gmtime` take a pointer?为什么`gmtime`需要一个指针?
【发布时间】:2016-04-25 10:02:25
【问题描述】:

根据documentation struct tm *gmtime(const time_t *timer); 应该将timer 指向的time_t 转换为故障时间。

现在他们决定让函数采用指向time_t 的指针而不是直接传递time_t 是有原因的吗?

据我所知,time_t 是算术类型,因此应该可以直接通过(我也认为它适合long 是合理的)。似乎还有对 NULL 指针的任何特定处理(这可能是传递指针的动机)。

我有什么遗漏吗?今天还有什么相关的吗?

【问题讨论】:

  • 我猜想在某个时候他们设想time_t 可能是struct,并且希望在这种情况发生时有效地处理这种情况。
  • @Sean 但问题仍然存在,为什么是指针?
  • @Sean,这里是 UNIXv7 的原型:struct tm * gmtime(tim) long *tim;。这里没有结构。
  • 可以扩展通过指针引用的结构,同时保持向后兼容。
  • @myaut 看看 UNIX v6 - 这是gmtime(tim) int tim[];(它返回一个指向 9 元素 int 数组的指针 - 有结构,但没有结构 tm)

标签: c time posix


【解决方案1】:

据我所知,这更像是一个历史怪癖。当 time.h 第一次被引入时,它的功能类似于time,它使用了一个无法返回的值(即:没有long int 等)。该标准定义了一个不起眼的 time_t 类型,它仍然为供应商以奇怪的方式实现留有很大的空间(它必须是一个算术类型,但例如没有定义范围或最大值) - C11 标准:

7.27.1 时间的组成部分。
[...]
3 .声明的类型为size_t(在7.19中描述);
clock_t

time_t
是能够表示时间的实数类型;
4.clock_ttime_t可表示的时间范围和精度分别为 实现定义。

size_t 在 C11 中被描述为 “是 sizeof 运算符结果的无符号整数类型;”

鉴于此,您的评论(“我认为它适合 long”是合理的)是可以理解的,但它是不正确的,或者至少是不准确的.例如,POSIX 要求 time_t 是整数 真正的浮点类型。 long 适合该描述,但不适合 longlong double 也适合。更准确的假设是 time_t 的最小大小是 32 位 int(至少到 2038 年),但 time_t 最好是 64 位类型。

无论如何,在那些日子里,如果无法返回值,唯一的选择就是将内存传递给函数(这是明智的做法)。
这就是为什么我们有这样的功能

time_t time(time_t *t);

两次设置相同的值实际上没有意义:一次通过返回它,一次使用间接,但参数在那里,因为最初,函数被定义为

time(time_t *t)

注意缺少返回类型,如果今天添加了time,它要么被定义为void time( time_t * ),要么委员会没有喝酒,意识到在这里传递指针的荒谬,他们会将其定义为time_t time ( void );

查看关于时间函数的 C11 标准,似乎函数行为的重点在于返回值。简单地提到了指针参数,但它肯定没有任何意义:

7.27.2.4 时间函数

1。概要

#include <time.h>
time_t time(time_t *timer);

2。说明

时间函数确定当前日历时间。该值的编码是 未指定。

3。返回

时间函数返回当前实现的最佳近似值 日历时间。如果不是日历时间,则返回值 (time_t)(-1) 可用的。如果 timer 不是空指针,则返回值也分配给它的对象 指向。

我们可以从中得到的主要信息是,就标准而言,指针只是获取函数返回值的次要方式。鉴于返回值表明出了点问题 ((time_t)(-1)),我认为我们应该将这个函数视为应该是 time_t time( void )

但是由于旧的实现仍在运行,而且我们都已经习惯了,它是应该被标记为弃用的东西之一,但因为它从来没有真正被弃用,它可能会成为其中的一部分永远的 C 语言...

函数使用像这样的time_t (const) 的唯一其他原因要么是历史原因,要么是为了在 time.h API 中保持一致的 API。 AFAIK 那是

TL;DR

出于历史、兼容性和一致性的原因,大多数 time.h 函数使用指向 time_t 类型的指针。


我知道我之前读过关于 time 函数早期的那些东西,here's a related SO answer

【讨论】:

  • 这是最可能的解释。硬件限制与性能、向后兼容性以及“当时这似乎是个好主意”的组合
  • 所以答案是“出于历史和一致性原因”。我不认为这是一个答案。
  • @trojanfoe 所以说“出于历史和向后兼容性的原因”。请参阅catb.org/esr/time-programming 了解更多信息。
  • 那会更有意义。
  • 您有相关标准的参考或引用吗?
【解决方案2】:

原因可能是在过去,参数不能大于整数,因此您不能传递 long 并且必须将其作为指针来传递。函数的定义从未改变。

【讨论】:

  • time_t 是一个整数。我认为这只是一个“错误”,因为没有充分的理由。
  • @trojanfoe:标准中没有任何内容可以确保time_t 是整数。它是算术类型,但不是 int(至少不需要:POSIX 允许使用整数类型和浮点类型,前提是基础类型是 either 32 位或 64 位跨度>
  • @trojanfoe,不,它没有。只有编译器支持插入代码,例如把两个本地词放在一起,把它当作一个更大的东西来处理。想想低位字的溢出不会自动增加高位字。当 C 只是一个汇编程序生成器时,您必须及时回想。
  • @trojanfoe 首先,它没有被称为time_t,它只是long。其次,将两个字压入堆栈比在一个机器寄存器中返回两个字更容易。
  • @trojanfoe "从一开始,C 就设法应对比原生大小更长的整数" 不正确。很早的 C 有 16 位 int 而没有 long
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-26
  • 2014-10-05
  • 1970-01-01
相关资源
最近更新 更多