我从您所说的假设 SomeObj 并不真正关心时间,它只是您需要存储时间的一些存储容器。我还假设在您的用例中,无论您存储什么格式您的时间不需要是可移植的,并且存储的时间将始终在生成它们的同一系统上使用。如果这些假设中的任何一个不正确,那么强制转换不是您的问题的合适解决方案(我在下面讨论更合适的解决方案,参考关于 的讨论localtime()
)。
将time_t
值存储在int64_t
变量,当然 sizeof(time_t) 必须小于或等于 sizeof(int64_t),因此您的代码需要对此进行断言检查。现在您不能只将 time_t 分配给 int64_t (这在大多数但不是所有系统上都可以正常工作),因为如果 time_t 是浮点类型,您可能会在转换时失去精度,并且在转换时回到 time_t 它可能不是相同的值(尽管它可能“接近”正确的值)。关键是,对于可移植代码,您不能对 time_t 值的格式做出任何假设。让我在这里重申一下,即使下面的代码是可移植的,该解决方案也不会生成本身可移植的时间值;即,如果您在一个系统上生成 time_t 值并且您的 SomeObj 将该值传输到另一个“系统” (即使在同一处理器上但由不同的编译器编译)为了在另一个系统上进行解释,另一个系统可能会也可能不会以相同的方式解释该值。为此,您需要将 time_t 转换为离散数字,也许通过localtime()
或者localtime_r()
,将该结构传输到其他系统,并通过 将其转换为该系统的 time_t 格式mktime()
。
在任何情况下,要以与解释无关的方式将 time_t 值填充到 uint64_t 中,您需要从 time_t 值的位置读取位作为 uint64_t。如果 time_t 没有 uint64_t 宽,您将读取额外的位,但这没关系;这些位是“不关心”位。然后要从 uint64_t 中读取 time_t 值,您需要从 uint64_t 的位置读取位作为 time_t。换句话说,您获取源变量的地址,将其转换为目标类型的指针,然后取消引用它。如果类型的大小不匹配,您要么将额外的垃圾位读入目标变量,否则您将丢失可能是垃圾位的位。这是您在代码中执行此操作的方法...
#include <time.h>
#include <assert.h>
struct SomeClass
{
int64_t i64;
void setValue(const int64_t v) { i64 = v; }
void getValue(int64_t& v) const { v = i64; }
};
#if 0 // Set to 1 for C style casting, or 0 for C++ style casting.
int main()
{
assert (sizeof(int64_t) >= sizeof(time_t));
// ...fundamental, otherwise nothing else has any hope of working
SomeClass SomeObj;
time_t t = 1349388030;
int64_t i = *((int64_t*)&t);
SomeObj.setValue(i);
int64_t ii;
time_t tt;
SomeObj.getValue(ii);
tt = *((time_t*)&ii);
assert (tt == t);
}
#else
int main()
{
assert (sizeof(int64_t) >= sizeof(time_t));
// ...fundamental, otherwise nothing else has any hope of working
SomeClass SomeObj;
time_t t = 1349388030;
int64_t i = *reinterpret_cast<int64_t*>(&t);
SomeObj.setValue(i);
int64_t ii;
time_t tt;
SomeObj.getValue(ii);
tt = *reinterpret_cast<time_t*>(&ii);
assert (tt == t);
}
#endif