如何在 32 位和 64 位机器的头文件中获得相同的结构?
我有一个对于 32 位和 64 位机器应该具有相同形状(至少大小相同,我认为偏移量会随之而来)的结构。
我们的结构是一个混淆的类型,大小是在构建时生成的,我们无法知道该类型是否会在 32 ou 64 位架构上使用。
这样做的最佳做法是什么?你有这样做的项目指针吗?
I have a structure which should have the same shape (at least same size, offsets will come with it I think) for 32 and 64 bits machines.
Our struct is an obfuscated type, the size is generated at build time, and we can't know if this type will be used on 32 ou 64 bit arch.
What is the best practice to do that? Do you have pointers of project doing so?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果我理解正确的话,您想要生成一个结构,该结构在 32 位系统上应具有与 64 位系统上完全相同的布局。
例如,假设您将生成以下结构:
那么这在 64 位上将具有与 32 位上不同的布局(在这种情况下,字符指针将具有不同的大小)。
如果您在旧的 DOS 系统上编译它,那么 int 将是 16 位而不是 32 位,并且您将再次拥有不同的布局。
解决这个问题的最佳方法是定义您自己的类型,并在您的结构中使用它们,如下所示:
然后在您的结构中使用这些类型。
如果您需要移植到不同的系统,您只需要检查您的 typedef。
对于某些类型(例如指针),这个技巧不起作用,因为没有适用于 32 位或 64 位指针的内置类型,所有指针都是相似的(如果我们忘记了旧的 DOS 远近) - 指针)。
对于这些类型,您可以使用宏。例如这样:
那么对于 64 位系统你只需要像这样定义 MY_POINTER:
对于 32 位系统你可以这样定义它:
所以对于 32 位系统我们添加 2 个指针字段而不是 1 个
。最后一种方法是,当您有 2 个指针时,这些宏将生成 2 个具有相同名称的成员。
您可以通过使用未命名的联合来解决此问题。像这样定义你的宏:
请注意,使用这个解决方案我忽略了字节排序的问题。如果你想解决这个问题,你需要更深入地研究。
If I understand correctly you want to generate a struct which should have exactly the same layout on a 32-bit as on a 64-bit system.
E.g. suppose that you would generate this struct:
Then this will have a different layout on 64-bit as on 32-bit (the char-pointer will have a different size in this case).
If you would compile this on an old DOS system, then int would be 16-bit instead of 32-bit and you would have again a different layout.
The best way to tackle this is to define your own types, and use these in your structure, like this:
Then use these types in your struct.
If you ever need to port to a different system, you only need to review your typedefs.
For some types (like for pointers), this trick doesn't work since there is no built-in type for 32-bit or for 64-bit pointers, all pointers are alike (if we forget about the old DOS far- and near-pointers).
For those types, you could use macro's. E.g. this:
Then for 64-bit systems you only need to define MY_POINTER like this:
For 32-bit systems you can define it like this:
So for 32-bit systems we add 2 pointer-fields instead of 1.
The problem with this last approach is that when you have 2 pointers, these macro's will generate 2 members with the same name.
You can solve this problem by using an unnamed union. Define your macro like this:
Notice that with this solution I ignored the problem of byte-ordering. If you want to solve that you need to dive deeper.
技术上可行,但在实践中并未使用。
处理此问题的标准方法是为 32 位和 64 位平台使用相同的头文件并且有两个版本的库。标头的 32 位客户端链接到 32 位库,同样适用于 64 位库
。如果最终 32 位结构的对象需要进入 64 位代码(反之亦然),则必须有一个执行转换的代码段。这就是 32 位 glibc 在 64 位内核上的工作方式。
进行转换的一种简单而缓慢的方法是在文本中序列化并反序列化回来。
Technically possible, but not used in practice.
Standard way of dealing with this issue is to have the same header file for both 32- and 64-bit platforms and have two builds of your library. A 32-bit client of your header links against a 32-bit library, same goes for 64.
If eventually an object of a 32-bit structure needs to get into a 64-bit code (or vice versa) there is must be a piece of code that does the conversion. This is how 32-bit glibc works on a 64-bit kernel.
A simple slow way of doing the conversion is to serialize in text and deserialize back.