C/C++:使用多体系结构支持读取和写入时间戳数据到文件
作者:互联网
来自/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
};
如果你想将这个结构写入一个文件,并且你希望你的程序读回来并拥有多个arch支持(即32位版本写入它,64位版本读取它),你将不得不做一些黑客攻击确保每个系统的大小相同.有没有人知道更好的方法来保持架构独立的时间戳?例如,我希望能够将一些结构(例如,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
};
由于函数(mktime(),time(),gmtime(),strftime())我用来操作struct tm似乎甚至没有看到struct tm结构中的最后两个字段,我只是使用整数作为占位符的位置,以便大小始终相同.但是,我仍然在寻找更好的解决方案……
编辑:我在上面的修复中使用的int类型可能是int32_t或选择的任何固定宽度类型.
解决方法:
在我看来,确保以可以在所需平台上回读的方式编写保存的数据不符合“黑客”的条件.然而,盲目地以二进制格式保存(可能是打包的)结构并期望容易且可移植地读回它.
您需要单独处理每个字段,因为编译器可能会在字段之间添加填充,这些填充将出现在结构的“二进制转储”中,但这完全取决于编译器,因此对于平台之间的互操作性非常不利.
我可能会决定结构的原生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()只是以已知(如big-endian)格式写入(并读取)32位整数的二进制表示,该格式定义明确且易于回读.平台.
更新:序列化字符串当然可以完全相同的方式完成,一种流行的格式与C的内存中布局相同,即0终止字符串数组.那你就得:
void string_serialize(FILE *out, const char* string);
int string_deserialize(FILE *in, char *string, size_t max);
这里,string_deserialize()函数必须具有缓冲区大小限制,因此它不会因readin太多而溢出任何内容.我想象返回值表示成功/失败,因此调用代码可以采取它想要的任何措施.
在上面,我没有瞄准空间最小化的序列化,因为一位评论者指出在运行时int的许多字段并不真正需要那么精确,所以它们可以被序列化为更小的东西.如果你想这样做,那么发明像int8_serialize()等适当的函数当然是微不足道的,并且对每个字段使用正确的函数.
标签:c-3,32bit-64bit,c,compatibility 来源: https://codeday.me/bug/20190826/1732101.html