21

我目前正在用 C 语言将 32 位应用程序转换为 64 位应用程序。该应用程序目前正在使用 x86 架构(Windows、osx、Unix、Linux)。因此,在开始编码之前,我想知道在转换应用程序时需要考虑什么。

4

8 回答 8

29
  1. 找出是谁写的。他们是白痴吗?他们是几年前的你吗?你能问他们问题吗?他们是否熟悉多个平台和系统的存在?了解程序作者的思维方式将有助于您在遇到问题时理解问题。
  2. 启动并运行 64 位机器/构建环境。
  3. 用 int 替换 long。完全清楚那LONG不是long
  4. 用和替换(int)&x演员表和打字intptr_t(unsigned int)&xuintptr_t
  5. 审计任何依赖转换结构来char*进行指针运算的东西。
  6. 正则表达式搜索 \<4\> 以防您假设4 = sizeof(void*)
  7. 耐心点。当您发现问题时,如果存在相同的问题,请查看其他地方,并将解决方案包装在宏中。
  8. 尽量不要使用#ifdef RUN64或类似的东西。如果 128 位平台流行起来,你会后悔的。
  9. 用一些集中的宏来封装您的所有更改,这些宏将隐藏程序中其他地方的可移植性差异。
  10. 使用覆盖率测试器来帮助确保你已经覆盖了所有内容(如果合适的话)

编辑按照评论的建议添加uintptr_t了注释。

于 2009-01-04T22:35:10.907 回答
9

一个尚未提及的潜在问题是,如果您的应用程序从磁盘读取或写入二进制数据(例如,使用 读取结构数组fread),您将不得不非常仔细地检查并且可能最终有两个读取器:一个用于遗留文件一个用于 64 位文件。或者,如果您小心地使用头文件中的诸如此类uint32_t的类型<stdint.h>,您可以重新定义您的结构以逐位兼容。在任何情况下,二进制 I/O都是需要注意的。

于 2009-01-04T22:49:10.083 回答
6

这实际上取决于应用程序及其编码方式。一些代码可以用 64 位编译器重新编译,它就可以工作,但通常只有在设计代码时考虑到可移植性才会发生这种情况。

如果代码对本机类型和指针的大小有很多假设,如果它有很多位打包技巧,或者它使用字节指定协议与外部进程通信,但使用一些关于本机类型大小的假设,那么它可能需要一些或很多工作才能获得干净的编译。

几乎每个强制转换和编译器警告都是需要检查的危险信号。如果代码一开始没有“警告干净”,那么这也表明可能需要进行大量工作。

于 2009-01-04T22:33:17.980 回答
5

如果您为您的值使用了正确的类型 - 例如。size_t, ptrdiff_t, uintptr_t, 固定大小的 int 类型stdint.h在适当的地方 - 并且没有硬编码值大小,您的代码应该开箱即用。

于 2009-01-04T22:30:27.907 回答
4

C 中 32 位和 64 位编程之间的两个主要区别是sizeof(void*)sizeof(long). 您将遇到的主要问题是大多数 Unix 系统使用定义 long 为 64 位的 I32LP64 标准,而 Win64 使用定义 long 为 32 位的 IL32LLP64 标准。如果您需要支持跨平台编译,您可能需要为 32 位和 64 位整数使用一组基于架构的 typedef,以确保所有代码的行为一致。这是作为 C99 标准的一部分的 stdint.h 的一部分提供的。如果您没有使用 C99 编译器,则可能需要滚动您自己的等价物

如其他地方所述,转换的主要关注点是假设sizeof(int) == sizeof(long) == sizeof(void*)代码、支持已写入磁盘的数据的代码和跨平台 IPC 的代码。

要详细了解这背后的历史,请查看 ACM Queue 中的这篇文章

于 2009-01-05T04:50:32.477 回答
3

切换到 64 位时面临的主要问题是指针的大小不同(64 位而不是 32 位 - duh)整数的大小和 long 的大小也可能不同,具体取决于平台。

为什么这是个问题?好吧,事实并非如此,除非您的代码假定 sizeof(int) == sizeof(void*)。这可能会导致讨厌的指针错误。

于 2009-01-04T22:31:12.053 回答
3

好吧,从根本上说,更改的数量相当少,但如果应用程序一开始没有仔细编写以使其具有一定的可移植性,这仍然是一项主要任务。

主要区别在于指针是 64 位宽的,大多数其他数据类型没有改变。int 仍然是 32 位,而 long 可能仍然是 32 位。因此,如果您的代码在整数和指针之间转换,那将会中断。类似地,任何依赖于成员特定偏移量的结构或类似结构都可能会中断,因为其他成员现在可能更大,因此会更改偏移量。

当然,你的代码一开始就不应该依赖这些技巧,所以在理想情况下,这根本不是问题,你可以简单地重新编译,一切都会正常工作。但你可能并不生活在一个理想的世界里...... ;)

于 2009-01-04T22:36:18.050 回答
2

已经有很多好的答案了。

考虑使用Gimpel Lint。它可以准确指出有问题的构造类型。如果您的经验与我一样,它还会向您展示系统中与 32/64 位端口无关的许多错误。

于 2009-01-05T11:22:31.077 回答