从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.youkuaiyun.com/w174504744/article/details/8678045
本文总结了从32位系统移植代码到64位系统时遇到的问题,包括指针转换错误、未声明的函数、常量有效性、sizeof的使用、符号扩展和内存消耗增加等。针对这些问题,提出了相应的解决策略,如正确处理指针类型、确保函数声明、使用带符号的常量、理解不同平台下的sizeof行为以及优化内存使用。

被折叠的 条评论
为什么被折叠?



