c++ - C/C++ : Reading and writing time stamp data to file with multi architecture support

标签 c++ c compatibility 32bit-64bit

来自/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/

相关文章:

c++ - CharConverter 未知错误

java - 在 Android App 中编译 Latex 文档

c - 程序不等待文本输入

c - 'typeof' 之前的预期表达式或 'typeof' 之前的预期主表达式

android - 为什么某些设备不支持我们的 Android 应用程序

定义成员函数的 c++ 语法,它接受 int 并在类外部返回指向 in 的指针

c++ - 参数相关的查找和函数模板

c++ - glob_recurse 在 cmake 中生成错误

memory - 笔记本电脑到台式机内存 RAM 适配器的可靠性

javascript - React Native 0.47 删除了 createJSModules 方法的向后兼容性