时间函数 localtime localtime_r

这篇具有很好参考价值的文章主要介绍了时间函数 localtime localtime_r。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

时间函数 localtime localtime_r
localtime 和 localtime_r 的函数功能: converts the calendar time timep to broken-time representation

在调用 localtime 和 localtime_t 函数时,需特别注意:

localtime 是不可重入函数,非线程安全

localtime_r 是可重入函数,线程安全

使用 localtime 时不可重入示范:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

int main()
{
    time_t curTime = time(NULL);
    time_t aftTime = curTime + 3600*3;

    struct tm *pTm1 = localtime(&curTime);
    struct tm *pTm2 = localtime(&aftTime);

    fprintf(stdout, "%04d%02d%02d%02d%02d%02d\n",
            pTm1->tm_year + 1900,
            pTm1->tm_mon + 1,
            pTm1->tm_mday,
            pTm1->tm_hour,
            pTm1->tm_min,
            pTm1->tm_sec);

    fprintf(stdout, "%04d%02d%02d%02d%02d%02d\n",
            pTm2->tm_year + 1900,
            pTm2->tm_mon + 1,
            pTm2->tm_mday,
            pTm2->tm_hour,
            pTm2->tm_min,
            pTm2->tm_sec);

    return 0;
}

编译 & 运行:

$ gcc -o main main.c
$ ./main
20180704225205
20180704225205

调用 localtime 函数并获取其返回值(一个指向 struct tm 结构类型数据的指针)后,我们并未对返回值进行显式地释放。

这并没有什么问题(不会导致内存泄漏)。

因为 localtime 函数返回值是一个指针,指向一个静态变量,这个静态变量是库中的一个 static struct tm 类型数据。

man localtime:

The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions.

这将引出新的问题,同一进程多个线程中同时调用(极短时间内连续调用) localtime 函数,返回值(tm)可能被覆盖。

举个栗子:

两个线程A和B同时调用 localtime 函数:

时刻1:线程A调用 localtime 函数,得到一个指针,指向 static struct tm 类型变量;(tm中存储的值更新为 value-a)

时刻2:线程B调用 localtime 函数,得到一个指针,指向 static struct tm 类型变量;(tm中存储的值更新为 value-b)

时刻3:线程A对 localtime 返回的指针进行相关引用操作(例如 printf 输出某字段),此时 static struct tm 中的值实际是 value-b,并非预期的 value-a

时刻4:线程B对 localtime 返回的指针进行相关引用操作,此时 static struct tm 中的值实际是 value-b

上面的示范代码虽然是在同一线程中,但是已经可以简单模拟这样的多线程执行调用流程。

如何解决?

localtime_r 是 localtime 的可重入版本(线程安全版本)。

localtime 不可重入是由于 static struct tm 是库中的一个静态变量,如果我们在调用 localtime 时传入一个 struct tm 类型变量(指针)用于存放结果,岂不是实现可重入?

Bingo!

struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);

调用 localtime 只需要传入指向 time_t 的一个常量指针;

调用 localtime_t 不仅需要传入指向 time_t 的一个常量指针,还需要传入指向 struct tm 的一个指针,结果将存储在 result 指向的 struct tm 对象中;

The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions.

The localtime_r() function does the same, but stores the data in a user-supplied struct.

使用 localtime_r 时可重入示范:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

int main()
{
    time_t curTime = time(NULL);
    time_t aftTime = curTime + 3600*3;

    struct tm tm1;
    struct tm tm2;
    localtime_r(&curTime, &tm1);
    localtime_r(&aftTime, &tm2);

    fprintf(stdout, "%04d%02d%02d%02d%02d%02d\n",
            tm1.tm_year + 1900,
            tm1.tm_mon + 1,
            tm1.tm_mday,
            tm1.tm_hour,
            tm1.tm_min,
            tm1.tm_sec);

    fprintf(stdout, "%04d%02d%02d%02d%02d%02d\n",
            tm2.tm_year + 1900,
            tm2.tm_mon + 1,
            tm2.tm_mday,
            tm2.tm_hour,
            tm2.tm_min,
            tm2.tm_sec);

    return 0;
}

编译 & 运行:

$ gcc -o main main.c
$ ./main
20180704200531
20180704230531文章来源地址https://www.toymoban.com/news/detail-801860.html

到了这里,关于时间函数 localtime localtime_r的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Docker容器与宿主机日期时间同步(日期同步、时间同步、容器时间、容器日期、docker时间、docker日期)/etc/localtime:ro、/etc/timezone:ro

    Docker容器的默认时区取决于使用的基础镜像。许多常见的基础镜像(例如Debian,Ubuntu等)的默认时区通常是UTC(协调世界时)。这意味着如果没有在创建或运行Docker容器时显式设置一个特定的时区,那么容器内部的时间将按照UTC来显示。 /etc/timezone : 这个文件包含了当前设置

    2024年02月05日
    浏览(30)
  • 【Go 基础篇】Go语言日期与时间函数详解:时间的掌控与转化

    Go语言是一种快速、简洁且高效的编程语言,它在处理日期与时间方面提供了丰富的标准库函数。本文将详细介绍Go语言中处理日期与时间的函数,涵盖常用的日期时间操作、格式化、时区转换等内容,并介绍 time.Time 结构体中的相关方法。 在Go语言中,时间被表示为 time.Tim

    2024年02月11日
    浏览(33)
  • “时间片轮转”调度算法(C语言)

    #define q 1 //时间片 要求: PCB必须按顺序输入,到达时间从小到大。 实现: 难点在于PCB就否到达就绪队列的处理。 设标识变量,处理就绪队列,队列内有有效PCB和无效PCB(还未到达) 刚到达的PCB与执行一次时间片之后的PCB排序问题: 课本解释:当该进程的时间片耗尽或运行

    2024年02月05日
    浏览(29)
  • [数据结构-C语言] 算法的时间复杂度

    目录 1.算法的复杂度 2.时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 3、常见时间复杂度计算举例 3.1 冒泡排序 3.2 二分查找 3.3 阶乘递归 3.4 斐波那契数列 1.算法的复杂度 算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此 衡量一个算法的

    2024年02月02日
    浏览(33)
  • 动态规划算法解决背包问题,算法分析与C语言代码实现,时间效率解析

    🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨,经典算法的解析✨都在这儿,欢迎大家前往订阅本专题,获取更多详细信息哦🎏🎏🎏 🪔本系列专栏 -  数据结构与算法_勾栏听曲_0 🍻欢迎大家  🏹  点赞👍  评论📨  收藏⭐️ 📌个人主

    2023年04月16日
    浏览(41)
  • 算法 时间、空间复杂度的计算(C语言/小白/零基础/新手 + 例题)

    目录 1. 时间复杂度 计算时间复杂度( O(N))的方法:   例1:嵌套循环时间复杂度的计算      例2:双重循环时间复杂度的计算   例3:常熟循环的时间复杂度   例6:冒泡排序的时间复杂度   例7: 二分查找的时间复杂度   例8:斐波那契的时间复杂度         常见的时间

    2024年02月08日
    浏览(32)
  • 初阶数据结构之---导论,算法时间复杂度和空间复杂度(C语言)

    数据结构其实也学了挺长时间了,说着是要刷题所以才没怎么去写关于数据结构方面的内容。数据结构作为计算机中及其重要的一环,如果不趁着假期系统整理一下着实可惜,我这里构想的是将初阶数据结构和高阶数据结构,分别分成两个部分,初阶数据结构呢,大概有以下

    2024年02月22日
    浏览(40)
  • 随机森林算法实现--R语言:randomForest函数

    在随机森林方法中,创建了大量的决策树。每个观察结果都被送入每个决策树。 每个观察结果最常用作最终输出。对所有决策树进行新的观察,并对每个分类模型进行多数投票。 随机森林首先是一种并联的思想,同时创建多个树模型,它们之间是不会有任何影响的,使用相

    2024年02月07日
    浏览(33)
  • 掌握Go语言:Go语言递归函数,解密编程之谜,探索算法的奥秘!(27)

    递归函数是指在函数内部调用自身的函数。在Go语言中,递归函数使用起来非常方便,但需要注意递归的终止条件,以避免无限循环。 Go语言递归函数的使用方法 在Go语言中,编写递归函数的基本步骤如下: 上述三点内容详细解释如下: 定义一个函数,函数内部调用自身 :

    2024年04月15日
    浏览(34)
  • 掌握Go语言:探索Go语言递归函数的高级奥秘,优化性能、实现并发、解决算法难题(28)

    递归函数在Go语言中是一种强大的工具,能够解决许多复杂的问题。除了基本的递归用法外,Go语言还提供了一些高级用法,使得递归函数更加灵活和强大。本文将深入探讨Go语言递归函数的高级用法,包括尾递归优化、并发递归和记忆化递归等。 尾递归优化 尾递归是一种特

    2024年04月10日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包