32位程序移植到64位平台前的准备工作

下面是做32位程序移植到64位程序时资料整理:

        将 32 位应用程序转换成 64 位应用程序时的主要问题是 int 类型相对 long 和指针类型的大小发生了变化。将 32 位程序转换成 64 位程序时,只有 long 类型和指针类型的大小从 32 位转换成 64 位;整数类型 int 的大小仍然保持为 32 位。这导致将指针类型或 long 类型赋值给 int 类型时会发生数据截断问题。而且,将使用小于 int 类型的表达式赋值给 unsigned long 或指针时,可能会发生符号位扩展问题。本文讨论如何避免或消除这些问题。  
考虑 32 位和 64 位数据模型之间的差异
       32 位和 64 位编译环境之间最大的不同之处在于数据类型模型的变化。32 位应用程序的 C 数据类型模型是 ILP32 模型,如此命名是因为 int 类型、 long 类型和指针都是 32 位数据类型。 64 位应用程序的数据类型模型是 LP64 数据模型,如此命名是因为 long 和指针类型变成了 64 位。其余 C 整数类型和浮点类型在这两种数据类型模型中相同。
当前的 32 位应用程序通常假设 int 类型、 long 类型和指针大小相同。因为在 LP64 数据模型中, long 和 pointer 发生了变化,这种变化正是导致 ILP32 到 LP64 转换问题的主要原因。

---------------------------------------------------------------------------------------------------------------------------------

从32位到64位,根本性的区别在于两种数据类型发生了变化:long和pointer,当你把pointer或者long型数据赋给int型时,会发生数据截断(data truncation)。


用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




留心union
union中的成员,必须保持平衡,也就是说,必须保证大小相等才有意义,所以移植时也要注意。
例如:
typedef union {
  double _d;
  long _l[2];
} llx_
在ILP32中,两者大小相同,都是8字节;移植到LP64,前者不变,后者为16字节,此时union已无意义,应改为:
typedef union {
  double _d;
  int _l[2];
} llx_


留心对齐
出于访问的效率,结构中通常会有所谓的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.


留心常量类型
在常量表达式中,精度的缺失会导致数据截断,例如:
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
例如,这些定义在sys/types.h中的数据类型,其大小会随ILP32或者LP64而变化:
    * clock_t, which represents the system time in clock ticks
    * dev_t, which is used for device numbers
    * off_t, which is used for file sizes and offsets
    * ptrdiff_t, which is the signed integral type for the result of subtracting two pointers
    * size_t, which reflects the size, in bytes, of objects in memory
    * ssize_t, which is used by functions that return a count of bytes or an error indication
    * time_t, which counts time in seconds


留心边缘效应
局部代码发生类型改变,可能导致其他代码发生64位转换,例如函数的返回值由Int变为sszie_t,则所有调用该函数并获取其返回值的地方,都有可能发生意想不到的64位转换
留心long array 对效率的影响
大型Long/unsigned long数组,在LP64下,相比ILP32,效率非常低,所以,如果int就足够,尽量不要使用Long,这一点,对于pointer arrary同样适用。
1.  对于long类型,会发生字节数变化,所以要检查所有使用long类型的地方;


2.  指针在32位系统中是4字节,而在64位系统中是8字节,因此所有跟指针字节数有关的地方必须改掉。典型的情况是:
      1)将struct类型直接存入文件再读出来,并且struct中包含指针成员。
      2)使用memset函数直接指定了大小,比如Student ** p = new Student*[num]; memset(p, 4, num);

-----------------------------------------------------------------------------------------------------------------------

主要注意点:指针 32位4个字节,64位8个字节;

                   long型32位4个字节,64位8个字节;

下面是相关资料链接:

  -----------------------------------------------------------------------------------------------------------------------            

32位C/C++程序移植到64位系统时需要注意的问题

https://blog.csdn.net/vistas_fh/article/details/50858001

 

C程序将32位代码向64位平台移植的注意事项

https://blog.csdn.net/bytxl/article/details/47813547

 

64位系统代码移植面临的20个问题

https://blog.csdn.net/john2xy/article/details/20312603

2位程序移植到64位平台前的准备工作_FrankieWang008的专栏-CSDN博客
https://blog.csdn.net/FrankieWang008/article/details/6885491?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.channel_param

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值