从32位系统移植代码到64位系统,会遇到很多意想不到的问题,需要确认代码兼容性,一般通过解决编译和测试中出现的缺陷来完成整个移植过程,现对移植过程中遇到的问题做下总结。
32位和64位的区别主要表现在参数类型长度上,区别如下:
参数类型 | 32位 | 64位 |
---|---|---|
char | 8 | 8 |
unsigned char | 8 | 8 |
short | 16 | 16 |
unsigned short | 16 | 16 |
int | 32 | 32 |
unsigned int | 32 | 32 |
long | 32 | 64 |
unsigned long | 32 | 64 |
long long | 64 | 64 |
point | 32 | 64 |
time_t/size_t | 32 | 64 |
遇到的问题
1. 强制转换
- 参数param的地址被截短为32位,指针类型转化为整形后,丢失高32位的指针数据,导致指针指向错误的地址,程序崩溃
sendMsg((int)¶m,TRUE);
- int型强转为time_t类型,可能导致参数值不准确
int time = 0; gmtime((time_t*)&time);
- 若time参数作为出参,会导致越界
int time = 0; gettime((time_t*)&time);
2. 函数未声明
void *function(void);
对于返回类型为指针的函数,必须在调用处包含声明,否则,编译器会默认将返回类型视为整形,将返回值截短为32位,程序崩溃
3. 常量有效性
#define INVALID_VALUE 0xFFFFFFFF
无符号32位常量0xffffffff用来测试是否为-1,但在64位系统中,这个值不是-1,而是4294967295,在64位系统中,-1正确的值应为0xFFFFFFFFFFFFFFFF。
要避免这个问题,在声明常量时,使用const,并且带上signed或unsigned。
const signed int INVALID_VALUE =0xFFFFFFFF;
4. sizeof使用
unsigned char *array[50];
unsigned char size = sizeof(array);
32-bit system: sizeof(array) = 200(50*4)
64-bit system: sizeof(array) = 400(50*8)
5. 符号扩展问题
要避免有符号数与无符号数的算术运算。
要想让表达式在 32 位和 64 位系统上都可以正确工作,请注意以下规则:
- 两个有符号整数相加的结果是一个有符号整数。
- int 和 long 类型的两个数相加,结果是一个long 类型的数。
- 如果一个操作数是无符号整数,另外一个操作数是有符号整数,那么表达式的结果就是无符号整数。
- int 和 doubule 类型的两个数相加,结果是一个 double 类型的数。此处 int 类型的数在执行加法运算之前转换成
double 类型。
6. 内存消耗问题
在升级到64位操作系统后,内存消耗也会随之增加。例如复杂的结构中会保存大量的指针类型,而这些指针类型在64位系统中,自身占用内存会大量增加。在内存消耗较多的程序中,升级时要评估升级代价。在必要的情况下,需要修改程序内部逻辑,以便节约空间消耗。
另外,由于字节对齐问题,也容易导致结构体的不正常膨胀。通过改变结构中数据排列的先后顺序,能将此问题所带来的影响降到最小,并能减少所需的存储空间。
参考
https://blog.csdn.net/w174504744/article/details/8678045