将 32 位代码移植到 64 位架构
如果您的代码已经可以在桌面或 iOS 平台上运行,那么您无需针对 Android 做额外的工作。如果这是第一次针对 64 位系统构建您的代码,那么您需要解决的主要问题是指针不再适合 int
这样的 32 位整数类型。您将需要更新以 int
、unsigned
或 uint32_t
等类型存储指针的代码。在 Unix 系统上,long
对应的是指针大小,但在 Windows 上并非如此,因此您应该改用释意类型 uintptr_t
或 intptr_t
。使用 ptrdiff_t
类型来存储两个指针之间的差异。
您应该始终选择使用 <stdint.h> 中定义的特定固定宽度整数类型,而不是 int
或 long
等传统类型,即便对于非指针也应如此。
使用以下编译器标记来捕捉代码在指针和整数之间转换不正确的情况:
-Werror=pointer-to-int-cast
-Werror=int-to-pointer-cast
-Werror=shorten-64-to-32
具有 int
字段(包含指向 C/C++ 对象的指针)的 Java 类也有同样的问题。在 JNI 源代码中搜索 jint
,并确保切换到 long
(Java 端)和 jlong
(C++ 端)。
因指针被截断而引起的崩溃将表现为 SIGSEGV,其中错误地址的前 32 位全部为零。
对于 64 位代码而言,隐式函数声明的危险性要高得多。C/C++ 假定隐式声明的函数(即编译器未检测到声明的函数)的返回值类型为 int
。如果函数的实际返回值类型是指针,那么在 32 位系统上是可行的,因为在 32 位系统中指针的类型为 int
,但在 64 位系统中,编译器会丢弃指针的前半部分。