来自/usr/include/time.h:
/* Used by other time functions. */
struct tm
{
int tm_sec;. . . /* Seconds..[0-60] (1 leap second) */
int tm_min;. . . /* Minutes..[0-59] */
int tm_hour;. . . /* Hours.. [0-23] */
int tm_mday;. . . /* Day... [1-31] */
int tm_mon;. . . /* Month.. [0-11] */
int tm_year;. . . /* Year.- 1900. */
int tm_wday;. . . /* Day of week..[0-6] */
int tm_yday;. . . /* Days in year.[0-365].*/
int tm_isdst;.. . /* DST... [-1/0/1]*/
#ifdef. __USE_BSD
long int tm_gmtoff;. . /* Seconds east of UTC. */
__const char* tm_zone;. / Timezone abbreviation. */
#else
long int __tm_gmtoff;.. /* Seconds east of UTC. */
__const char* __tm_zone;. / Timezone abbreviation. */
#endif
};
如果你想把这个结构写到一个文件中,并且你想让你的程序读回它并支持多体系结构(即 32 位版本写入它,64 位版本读取它),你必须做一些 hack 以确保每个系统的大小相同。有谁知道更好的方法来保持独立于体系结构的时间戳?例如,我希望能够将一些结构(例如 time_t 或 struct tm)写入文件,并针对任何体系结构将其读回。有没有人对此有任何经验或建议? struct tm 是在 C/C++ 中存储时间戳的最佳方式吗?我意识到使用这种结构会产生一些开销。
我目前已将结构重新定义为以下内容:
//Force 32 bit format and space requirements
struct tm32
{
int tm_sec;. . . /* Seconds..[0-60] (1 leap second) */
int tm_min;. . . /* Minutes..[0-59] */
int tm_hour;. . . /* Hours.. [0-23] */
int tm_mday;. . . /* Day... [1-31] */
int tm_mon;. . . /* Month.. [0-11] */
int tm_year;. . . /* Year.- 1900. */
int tm_wday;. . . /* Day of week..[0-6] */
int tm_yday;. . . /* Days in year.[0-365].*/
int tm_isdst;.. . /* DST... [-1/0/1]*/
int tm_gmtoff; // this does nothing but hold space
int tm_zone; // this does nothing but hold space
};
因为我用来操作 struct tm 的函数 (mktime(), time(), gmtime(), strftime()) 似乎甚至没有查看 struct tm 结构中的最后两个字段,我简单地使用整数作为位置的占位符,这样大小将始终相同。但是,我仍在寻找更好的解决方案...
编辑:我在上述修复中使用的 int 类型可以是 int32_t 或任何选择的固定宽度类型。
最佳答案
在我看来,确保以可在所需平台上读回的方式写入保存的数据不符合“hack”的条件。然而,盲目地以二进制格式保存一个(可能是打包的)结构并期望能够轻松、便携地读回它。
您需要单独处理每个字段,因为编译器可能会在出现在 struct
的“二进制转储”中的字段之间添加填充,但这完全取决于编译器,因此非常不利于平台间的互操作性。
我可能会为结构的 native int
字段确定一个合理的精度,比如说 32 位,然后写这样的东西:
void tm_serialize(FILE *out, const struct tm *tm)
{
int32_serialize(out, tm->tm_sec);
int32_serialize(out, tm->tm_min);
/* and so on */
}
struct tm tm_deserialize(FILE *in)
{
struct tm tm;
tm.tm_sec = int32_deserialize(in);
tm.tm_min = int32_deserialize(in);
/* and so on */
return tm;
}
当然,int32_serialize()
和 int32_deserialize()
只是简单地写入(和读取)32 位整数的二进制表示形式(例如big-endian) 格式,定义明确且易于在任何平台上读取。
更新:序列化字符串当然可以用完全相同的方式完成,一种流行的格式与 C 的内存布局相同,即以 0 结尾的 char
大批。那么你只需:
void string_serialize(FILE *out, const char* string);
int string_deserialize(FILE *in, char *string, size_t max);
这里,string_deserialize()
函数必须有一个缓冲区大小限制,这样它就不会因为读入太多而溢出任何东西。我想象返回值指示成功/失败,因此调用代码可以采取任何它想要的措施。
在上面,我的目标不是空间最小化的序列化,因为评论者指出许多在运行时为 int
的字段并不真正需要那么精确, 所以他们可以序列化成更小的东西。如果您想这样做,发明适当的函数(如 int8_serialize()
等)并为每个字段使用正确的函数当然是微不足道的。
关于c++ - C/C++ : Reading and writing time stamp data to file with multi architecture support,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8412517/