【问题标题】:How to cast unsigned long to time_t in 64-bits如何以 64 位将 unsigned long 转换为 time_t
【发布时间】:2018-08-08 16:28:16
【问题描述】:

我正在使用 MSVC6 (Visual Studio 98) 以 32 位的 C++ 调用本地时间:

localtime((time_t *)&FileData.LastAccessDateTime)

FileData.LastAccessDateTime 是一个无符号长整数,它在 32 位中编译并运行良好。我现在正在使用 VS2017 转换代码。它在 64 位中编译得很好,但它在运行时在 localtime b/c 内崩溃,传递给 localtime 的高位 dword 充满了垃圾。我知道我可以将 FileData.LastAccessDateTime 分配给一个临时 time_t 变量,然后获取它的地址。但我想在不创建本地临时变量的情况下解决这个问题,因为我必须在代码中的 100 个其他地方修复这个问题。我尝试将 FileData.LastAccessDateTime 转换为 __int64 但我收到编译错误消息:“&”需要左值。这对我来说似乎很奇怪 b/c FileData.LastAccessDateTime 在内存中有一个物理地址,我只是改变了查看它的方式(或者我认为)。

那么,我怎样才能在一行中更改此转换,以正确地将 unsigned long 向上转换为 time_t 值?

【问题讨论】:

  • 1.这是否需要是线程安全的(我假设重入对于本地时间来说不是问题)? 2. 使用集中声明的函数是一种选择吗?
  • 我怀疑在您声明的“数百个”地方正确解决此问题所需的时间将少于尝试解决钝角解决方法所需的时间。您可以尝试制定 _USE_32BIT_TIME_T 解决方案,但恕我直言,这是一个糟糕的解决方法。
  • 修复代码怎么样?我的意思是,把localtime调用放到一个单独的函数里,把转换放到这个函数里,在那100个地方调用这个函数而不是localtime。
  • @MaxLanghof:是的,它需要是线程安全的。所以,没有全局变量。 @Whoz:这个 64 位代码不能使用 _USE_32BIT_TIME_T。 @geza:是的,正如您和 Max 提到的那样,一个单独的功能可能是要走的路。

标签: c++ casting 64-bit


【解决方案1】:

问题的核心是我们需要提供一个指向localtime 的8 字节大小的内存位置的指针,而FileData.LastAccessDateTime 的内存位置只有4 字节。所以,我们需要在别处抢占一些空间。

选项 1: 8 字节空间将位于 。应该这样做:

localtime(std::make_unique<time_t>(FileData.LastAccessDateTime).get());

unique_ptr 处理堆分配和清理。当然,这每次都会花费您一次内存分配。是否可以由您决定。

选项 2: 8 字节空间将在 堆栈 上。这里无法绕过函数局部对象,但您可以将其包装成一个便利函数(希望您可以在所有这 100 个地方都使用该函数):

struct tm * localtime64comp(uint32_t* timer32)
{
  uint64_t timer64 = timer32;
  return localtime(timer64);
}

// ...

localtime64comp((time_t *)&FileData.LastAccessDateTime);

如果你不能让这个功能无处不在,这似乎是不可行的。

选项 3: 使用 global (ugh) 作为空间。

uint64_t LOCALTIME_COMP;

// ...

localtime(&(LOCALTIME_COMP = FileData.LastAccessDateTime));

这显然不是线程安全的(编辑:我猜你可以使它成为线程本地的)并且仍然存在同样的可用性问题,所以我会避免它。但它会起作用。

【讨论】:

  • 谢谢。是的,单独的功能(选项 2)是一个不错的方法。
猜你喜欢
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-01
  • 2016-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多