固定大小的结构体

3
struct my_struct
{
  char  a;
  short b;
  int   c;
};

sizeof(my_struct) 在不同的计算机上可能会有所不同(特别是任何标准C++类型的大小可能会有所不同)。 这还取决于内存对齐等因素(如#pragma pack(*)等)。 那么实现固定大小结构体的最佳方法是什么?


@herohuyongtao 我想要读写文件。由于 my_struct 的大小可能不同,所以在不同机器上编译的应用程序无法使用创建的文件。 - Ivars
1
@herohuyongtao:在进程间通信中,需要控制和了解结构的大小非常普遍。当通过网络与运行不同操作系统的机器进行通信时,这一点尤为重要,而且您不希望将所有内容都表示为字符串。 - John Dibling
3个回答

2

无论你做什么,都不能保证一个结构在所有可能的实现中都具有相同的大小。大约最接近的方法可能是:

struct my_struct { 
    char contents[some_size];
};

这至少保证了在所有实现中内容的大小将是相同的。然而,实现仍然可以在内容之后插入填充,因此在不同的实现中仍可能得到不同的大小。


但是如何将结构体读写到文件中呢?它必须以某种方式固定大小。位图头结构体必须是固定大小的,因为其头部的大小已经记录在文档中。 - Ivars
你写入文件的内容不需要与内存中的内容完全匹配。如果你真的关心可移植性,通常只需将单个字段写入文件,从而消除大部分可能的填充(但即使这样也不能绝对保证可移植性)。 - Jerry Coffin
那么像 DummyWrite(FileHandle, &my_struct, sizeof(my_struct)) 这样的写法是错误的吗?如果我有成千上万个字段怎么办?我必须手动编写所有这些字段吗?那太可怕了! - Ivars
如果你有成千上万的字段,那么你做错了其他事情。不管怎样,你也可以考虑使用一些旨在使这种工作变得更简单的库(例如Google Protocol Buffers)。 - Jerry Coffin

2
如果您能对目标平台有一定的现实和了解,那么您可以很容易地找到一些共同点,并以此为结构的基础。
例如,如果您的目标平台是在当前x86硬件上运行的Windows和Linux,则您已经知道一些东西:
  • char 标准中确切为1字节
  • 1字节等于8位
  • int8_tuint8_t 在C++11下确切为8位(大多数C++03编译器也提供这些)
  • int16_tuint16_t 在C++11下确切为16位
  • int32_tuint32_t 在C++11下确切为32位
  • int64_tuint64_t 在C++11下确切为64位
  • C风格的ASCII字符串是以NULL结尾的char数组
  • 预处理指令可用于控制打包

字节序仍然是个问题,所以在转换多字节类型时需要处理这个问题。

试图设计一个结构体,在所有奇特的平台上都保证有相同的二进制表示方式是不可能的。如果只使用char,你可以接近这个目标,但即使如此也不能保证因为你不知道一个字节里面有多少个位。

你可以尝试使用位域来表示你的数据,但你仍然不知道一个字节里面有多少个位,所以你无法确定会添加多少填充位于结尾。

可移植性有其作用:可移植代码比特定平台的代码更易于维护和扩展。追求可移植性仅为了“可移植性”的学术目标在专业编程中没有任何意义。另一方面,为了“可维护性”而追求可移植性是一个值得称赞的目标,但也需要权衡取舍。如果你想出一个完全可移植的解决方案,可以在所有可能的平台上运行,但只能在其中两个平台上运行,并且你的代码难以维护,那么这还有什么意义呢?

谢谢!我有一些需要写入文件并进行读取的结构体。如果我希望我的项目在多个平台上都能够移植,这是否意味着我必须为每个平台实现一个结构体? - Ivars
@user2543574:不需要。你只需要实现一个结构体,其中只使用每个平台已知的字段。但是,你需要为每个平台实现字节序转换。 - John Dibling
有点离题了.. __int* 和 int*_t 有什么区别? - Ivars
__int*是特定于平台的。int*_t由标准定义。 - John Dibling
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/45130/discussion-between-user2543574-and-john-dibling - Ivars
显示剩余2条评论

1

3
“Works on 2 compilers”并不等同于“可移植”。 - Alan Stokes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接