【问题标题】:C - timeval to uint64_tC - 到 uint64_t 的时间
【发布时间】:2020-08-04 08:54:07
【问题描述】:

早上好!

我正在尝试从 timeval 结构中获取纳秒时间戳 (uint64_t)。

    struct timeval t;
    // initialized so that ....
    print("t sec: %ld, micro sec: %ld", t.tv_sec, t.tv_usec);
    // .... prints "t sec: 4, micro sec: 130728"

    long int sec = (long int) t.tv_sec;
    // just did that because I thought that using time_t in calculations may cause errors
    // print("%ld", sec) -> 4, so this seems to work as expected    

    uint64_t t_int = (sec * 1000000 + t.tv_usec) * 1000; // should be nanoseconds
    print("t_int (uint64_t) %llu", t_int);
    // prints "t_int (uint64_t) 18446744073545312320"

我的 timevals 绝对应该适合 uint64_t。此外,从 time_t 转换为 long int 有效,所以我所做的只是用两个 long int 进行简单计算,将结果放入 uint64_t,所以我不确定为什么我得到一个明显错误的值。有任何想法吗?这只是一种错误的格式化方式(使用 %llu)吗?

【问题讨论】:

  • 你的机器上long int 的大小是多少? sec 的价值是多少?您是否知道您的计算sec * 1000000 是使用long int 而不是uint64_t 完成的?以及该 sn-p 中的所有其他计算。
  • printf("t_int (uint64_t) %"PRIu64,t_int); 带有正确格式化程序的 uint64_t 代码。见here

标签: c timeval


【解决方案1】:

要么:

uint64_t t_int = ((uint64_t)t.tv_sec * 1000000 + t.tv_usec) * 1000;

或:

uint64_t t_int = (t.tv_sec * 1000000ULL + t.tv_usec) * 1000;

后者跳过强制转换,而是通过使* 的右侧操作数已经是至少为 64 位的类型来执行提升(而不是将左侧强制转换为 1)。要么工作;看你喜欢什么风格。

不要像以前那样使用 long 类型的临时变量。 long 可能是 32 位类型,不适合 2038 年 1 月以后的时间。如果您需要临时变量,请将其设为 time_tint64_t 或类似名称。但这不是必需的。

您还可以考虑使用int64_t(并将ULL 更改为LL)而不是uint64_t,这样您就可以表示1970 年之前的时间。

【讨论】:

  • “考虑使用int64_t”是个好主意,因为specified .tv_usec.tv_sec 肯定是有符号数量。
  • 谢谢,工作完美。不过我会保持它不签名,因为我用它来计算从开始到停止时间的时间。
【解决方案2】:

您正在使用long int 宽度进行计算。因为它溢出了未定义的行为,并且一些负值被分配给uint64_t,这导致了一个很大的正值(在你的架构上)。使用uint64_tunsigned long long 精度进行计算。为了迂腐,请转换所有值:

uint64_t t_int = ((uint64_t)sec * 1000000ull + (uint64_t)t.tv_usec) * 1000ull; 

但由于促销活动,很可能只需将一个值转换为 uint64_t 就足够了:

uint64_t t_int = ((uint64_t)sec * 1000000 + t.tv_usec) * 1000;

【讨论】:

  • 即使存储long int sec = (long int) t.tv_sec; 也是一个错误。它将在 32 位长的实现上溢出 Y2038。相反,您只想直接使用t.tv_sec,或者如果您坚持使用sec,则将无用的临时变量time_t设置为类型。
猜你喜欢
  • 2020-07-03
  • 1970-01-01
  • 2014-03-05
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
相关资源
最近更新 更多