Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C/C++;:通过多体系结构支持将时间戳数据读写到文件_C++_C_Compatibility_32bit 64bit - Fatal编程技术网

C++ C/C++;:通过多体系结构支持将时间戳数据读写到文件

C++ C/C++;:通过多体系结构支持将时间戳数据读写到文件,c++,c,compatibility,32bit-64bit,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_

从/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位版本读它),你必须做一些黑客,以确保每个系统的大小相同。有谁知道更好的方法来保持独立于体系结构的时间戳吗?例如,我希望能够将一些结构(例如,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\u t或选择的任何固定宽度类型

确保文件完全独立于平台的一种方法是使用文本文件


否则,在转换后的结构中包括
,并使用类似
uint32\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结尾的
char
数组。那么你就只有:

void string_serialize(FILE *out, const char* string);
int  string_deserialize(FILE *in, char *string, size_t max);
在这里,
string\u deserialize()
函数必须有缓冲区大小限制,这样它就不会因为读取太多而溢出任何内容。我设想返回值表示成功/失败,因此调用代码可以采取它想要的任何措施


在上面的文章中,我的目标不是最小化空间的序列化,正如一位评论员指出的那样,许多在运行时为
int
的字段实际上并不需要那么高的精度,因此可以将它们序列化为更小的字段。如果您想这样做,当然可以发明适当的函数,如
int8_serialize()
等,并为每个字段使用正确的函数。

struct tm
通常与C/POSIX时间函数一起使用。假设您没有在这些函数允许的范围之外使用它,有两种明显的方法:

  • 使用
    strftime
    写入,使用
    strptime
    读取。优点:非常容易理解以正常时间格式写入的输出数据(例如,使用ISO格式)
  • 调用
    mktime
    将其转换为
    time\u t
    ,然后将其写入二进制或ASCII。另一个方向是
    localtime
    gmtime
    。优点:小,二进制通常为4或8字节。对于ASCII,没有大多少

gettimeofday(2)
将返回自历元以来的秒数和微秒数;由于时间的类型为
time\u t
,它可能是32位(放置时间的位置)或更大,因此明智的做法是将
time\u t
强制转换为
uint64\u t
。使用工具以指定的字节顺序存储64位整数。

uint32\u t
实际上不会保护您,因为一个体系结构可能是大端,而另一个是小端。或者可能总是有不同的填充。+1-这是序列化结构的通用方法。挑剔:如果要打包,几乎所有这些字段的合适大小都是
uint8\u t
tm_year
可能需要更多(甚至是有符号类型),而
tm_gmtoff
需要更大和有符号。这解决了存储整数字段的问题,但我仍然需要为char*和long int成员创建标准的固定宽度字段(范围从32位到64位)。在不修改现有数据结构的情况下,使用strftime和strptime听起来是一个不错的解决方案。我看不出我的使用会超出C/POSIX时间函数的预期用途。伊玛,试试看。