32位程序移植到64位需要考虑的问题
2014-12-10 09:19
323 查看
(翻译自:http://developers.sun.com/prodtech/cc/articles/ILP32toLP64Issues.html)
概述
从32位到64位,根本性的区别在于两种数据类型发生了变化:long和pointer。在32位环境下,顾名思义,两者长度都是32位,也就是4个字节;而在64位环境下,都是8个字节。所以,当你把pointer或者long型数据赋给int型时,会发生数据截断(data truncation)。
32位与64位数据模型之间的区别
32位应用的数据模型我们称作ILP32(之所以这样命名,是因为int,long,pointer都是32位),而64位应用则采用LP64模型(意味着long,pointer变成64位了,其他的不变),在当前的32位环境下,我们可以认为int,long,pointer是等价的,因为它们占用相同的字节嘛,于是,就有很多混用的情况;但是,到了64位的时代,long和Poniter的大小都改变了,原来的假设不再成立。
用lint检测long/pointer的64位问题
采用-errchk=longptr64选项可以检查出把long/pointer表达式转换为int的情况,包括显式转换。
留心int和pointer
因为integer与pointer大小相同,所以32位代码中常常把pointer转换为int或者unsigned int,以便算术运算。为了移植,你可以把pointer转换为unsigned long,因为long和pointer都是等长的,无论是在ILP32亦或LP64,但是,为了使代码更清晰,推荐用uintptr_t,uintptr_t和intptr_t都需要包含头文件inttypes.h。
例如:下面代码在64位环境下编译出错:
char *p;
p = (char *) ((int)p & PAGEOFFSET);
% cc ..
warning: conversion of pointer loses bits
改用uintptr_t后,无论是32位或者64位都没问题:
char *p;
p = (char *) ((uintptr_t)p & PAGEOFFSET);
留心int和long
在ILP32中,可能从未对int和long加以区分,因此,混用的情况非常多,看下面代码:
int waiting;
long w_io;
long w_swap;
...
waiting = w_io + w_swap;
% cc
warning: assignment of 64-bit integer to 32-bit integer
留心对齐
出于访问的效率,结构中通常会有所谓的hole,用来保证其中的所有数据成员,起始地址都是对齐模数的倍数。
例如:
struct bar {
int i;
long j;
int k;
char *p;
};
在ILP32中,sizeof(bar)应该是16字节;在LP64中,应该是32!因为此时long/char *的对齐模数都变为8,为了保证满足对齐要求,i/k都被扩展为8字节了。
又例如:
struct bar {
char *p;
long j;
int i;
int k;
}
此时,无需扩展,sizeof(bar)=8+8+4+4=24.
留心union
union中的成员,必须保持平衡,也就是说,必须保证大小相等才有意义,所以移植时也要注意。
例如:
typedef union {
double _d;
long _l[2];
} llx_
在ILP32中,两者大小相同,都是8字节;移植到LP64,前者不变,后者为16字节,此时union已无意义,应改为:
typedef union {
double _d;
int _l[2];
} llx_
留心常量类型
在常量表达式中,精度的缺失会导致数据截断,例如:
int i = 32;
long j = 1 << i;
warning: left shift count >= width of type
什么意思?编译器抱怨左移的位数超过了数据类型的长度,结果就是j为0。
怎么修改呢?
int i = 32;
long j = 1L << i:
即可。
留心printf系列函数
在格式化串中,要注意:
%p兼容ILP32和L64。
如果有long型参数,必须加上l前缀;
另外就是作为目标的buffer必须够长。
留心sizeof
sizeof返回类型为unsigned long,如果返回给int型变量,可能发生截断。
留心derived data types
概述
从32位到64位,根本性的区别在于两种数据类型发生了变化:long和pointer。在32位环境下,顾名思义,两者长度都是32位,也就是4个字节;而在64位环境下,都是8个字节。所以,当你把pointer或者long型数据赋给int型时,会发生数据截断(data truncation)。
32位与64位数据模型之间的区别
32位应用的数据模型我们称作ILP32(之所以这样命名,是因为int,long,pointer都是32位),而64位应用则采用LP64模型(意味着long,pointer变成64位了,其他的不变),在当前的32位环境下,我们可以认为int,long,pointer是等价的,因为它们占用相同的字节嘛,于是,就有很多混用的情况;但是,到了64位的时代,long和Poniter的大小都改变了,原来的假设不再成立。
用lint检测long/pointer的64位问题
采用-errchk=longptr64选项可以检查出把long/pointer表达式转换为int的情况,包括显式转换。
留心int和pointer
因为integer与pointer大小相同,所以32位代码中常常把pointer转换为int或者unsigned int,以便算术运算。为了移植,你可以把pointer转换为unsigned long,因为long和pointer都是等长的,无论是在ILP32亦或LP64,但是,为了使代码更清晰,推荐用uintptr_t,uintptr_t和intptr_t都需要包含头文件inttypes.h。
例如:下面代码在64位环境下编译出错:
char *p;
p = (char *) ((int)p & PAGEOFFSET);
% cc ..
warning: conversion of pointer loses bits
改用uintptr_t后,无论是32位或者64位都没问题:
char *p;
p = (char *) ((uintptr_t)p & PAGEOFFSET);
留心int和long
在ILP32中,可能从未对int和long加以区分,因此,混用的情况非常多,看下面代码:
int waiting;
long w_io;
long w_swap;
...
waiting = w_io + w_swap;
% cc
warning: assignment of 64-bit integer to 32-bit integer
留心对齐
出于访问的效率,结构中通常会有所谓的hole,用来保证其中的所有数据成员,起始地址都是对齐模数的倍数。
例如:
struct bar {
int i;
long j;
int k;
char *p;
};
在ILP32中,sizeof(bar)应该是16字节;在LP64中,应该是32!因为此时long/char *的对齐模数都变为8,为了保证满足对齐要求,i/k都被扩展为8字节了。
又例如:
struct bar {
char *p;
long j;
int i;
int k;
}
此时,无需扩展,sizeof(bar)=8+8+4+4=24.
留心union
union中的成员,必须保持平衡,也就是说,必须保证大小相等才有意义,所以移植时也要注意。
例如:
typedef union {
double _d;
long _l[2];
} llx_
在ILP32中,两者大小相同,都是8字节;移植到LP64,前者不变,后者为16字节,此时union已无意义,应改为:
typedef union {
double _d;
int _l[2];
} llx_
留心常量类型
在常量表达式中,精度的缺失会导致数据截断,例如:
int i = 32;
long j = 1 << i;
warning: left shift count >= width of type
什么意思?编译器抱怨左移的位数超过了数据类型的长度,结果就是j为0。
怎么修改呢?
int i = 32;
long j = 1L << i:
即可。
留心printf系列函数
在格式化串中,要注意:
%p兼容ILP32和L64。
如果有long型参数,必须加上l前缀;
另外就是作为目标的buffer必须够长。
留心sizeof
sizeof返回类型为unsigned long,如果返回给int型变量,可能发生截断。
留心derived data types
相关文章推荐
- 32位程序移植到64位需要考虑的问题
- 32位程序移植到64位需要考虑的问题
- 32位程序移植到64位需要考虑的问题
- 32位程序移植到64位需要考虑的问题
- 32位C/C++程序移植到64位系统时需要注意的问题
- 32位C/C++程序移植到64位系统时需要注意的问题
- 移植32位程序到64位时碰到精度问题
- C/C++ 32位机器和64位机器 差异问题总结 跨平台 移植问题 语言编程需要注意的64位和32机器的区别
- 关于32位程序在64位系统下运行中需要注意的重定向问题(有图,很清楚)
- 关于32位程序在64位系统下运行中需要注意的重定向问题(有图有真相)(***)
- MSCRM4.0 - 在64位MSCRM4.0 环境中运行32位程序出现的问题及解决方案
- 32位程序到64位程序移植
- 32位程序在64位Windows7/2008下写注册表不起作用问题
- 如何移植32位程序到64位系统
- 32位到64位程序移植
- Linux 32位向64位移植的一些问题及解决
- 【Delphi】32位源码编译64位程序时的字节对齐问题
- Linux 32位向64位移植的一些问题及解决
- 应对32位程序在64位系统上访问注册表和文件自动转向问题
- 应对32位程序在64位系统上访问注册表和文件自动转向问题