【问题标题】:Copying struct tm复制 struct tm
【发布时间】:2017-09-26 09:22:51
【问题描述】:

glibc 版本的 struct tm 有额外的字段

long tm_gmtoff;           /* Seconds east of UTC */
const char *tm_zone;      /* Timezone abbreviation */

(参考:http://linux.die.net/man/3/ctime) 我的问题是:如果我有一个名为 struct tm a 的数据,并且我想将其复制到另一个 struct tm b,请按照以下代码:

time_t t = time(0);
const tm *pa = localtime(&t);
struct tm a;
if(pa) {
    memcpy(&a, pa, sizeof(a));
}

但是,tm_gmtoff 和 tm_zone 会发生什么?如何也复制这些字段?

【问题讨论】:

  • 为什么这两个字段不会被复制?
  • 将此移至答案...
  • 对于感兴趣的人,这里有一个现代的、线程安全的、跨平台的、用于处理时区相关问题的 C++11/14/17 库:howardhinnant.github.io/date/tz.html

标签: c++ glibc tm time-t


【解决方案1】:

这是您的编译器的工作。它将采取一切必要措施。
做吧:

struct tm a = *localtime(&t);

【讨论】:

  • 只为那些对所有权感兴趣的人:stackoverflow.com/a/8694379/978486
  • 但是 tm_zone 是一个字符数组,复制不会是深拷贝,而是共享指针的浅拷贝
  • 确实如此。但是我读到的是时区值被忽略了,而是使用了区域设置。这里可能是错的,但我认为这就是它的工作原理
  • 在某些情况下这似乎会崩溃。这里是复制者的链接:gitlab.xfce.org/xfce/thunar/-/issues/700#note_40990
  • 因此,按照此答案中的建议进行操作显然是个坏主意。这里是本地时间的一些文档:pubs.opengroup.org/onlinepubs/009604499/functions/….... If an error is detected, localtime() shall return a null pointer and set errno to indicate the error. 因此,如果localtime 返回 NULL,则建议的代码将崩溃。
【解决方案2】:

由于locatime() 可能返回一个空指针,避免

const struct tm a = *localtime(&t);  // Potential UB.

相反,测试是否为空,然后使用= 进行复制。 memcpy() 不需要。将复制所有struct tm 成员。

struct tm a = { 0 }; // Fill in a default value
const tm *pa = localtime(&t);
if (pa) {
  a = *pa;
}

OP cmets But tm_zone being a character array,但这是不对的。 tm_zone 不是字符数组,而是指向const 字符数组的指针。在这里复制那个指针就可以了。

【讨论】:

  • 不确定仅复制 tm_zone 的指针是否足够。这在很大程度上取决于用例......系统的 tm 会发生变化,我们持有指针的时区也会发生变化。例如。看这里:stackoverflow.com/questions/24026224/…
  • *pa 中的指针或a 中的指针在下一次localitme()/gmtime() 调用之前肯定是有效的。到那时,就足够了。在那之后它可能仍然没问题 - linux 对实现特定问题保持沉默。代码可以a = *pa;, a.tm_zone = strdup(pa->tm_zone); 然后管理字符串。您的观点是有效的,但 OP 的用例缺乏细节。
【解决方案3】:

我认为在大多数情况下只需要memcpy 是正确的做法。

但是,tm_gmtoff 和 tm_zone 会发生什么?如何也复制这些字段?

根据the doc you linked,只有在包含<time.h> 之前设置了_BSD_SOURCE 时,这些字段才会出现。

因此,如果您使用的是_BSD_SOURCE,则需要在tm_zonememcpy 之后使用strcpy

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    • 2011-01-24
    • 2016-05-25
    • 2015-05-06
    • 1970-01-01
    • 2015-04-05
    • 2016-07-02
    相关资源
    最近更新 更多