linux32位系统移植64,移植linux 应用到64-bit系统

Linux 是同时支持32-bits和64-bit跨平台的操作系统。随着双核机器越来越多,因此有很多应用需要适应不同的操作系统,也就是说需要同时兼容32位和64位。

首先我们来看32-bits和64-bits对C语言标准支持的不同。从表一可以看,通常LINUX32-bit 使用ILP32,而64-bits使用LP64标准,在32-bits标准中,int, long,pointer都是分配32it,

而64-bits系统中则不一样,pointer和long 是64位,但是int是32位。

34de9add2ae64c03120d71b77bbf0fee.gif

由于这两种系统的主要不同点是在long和point上,而这两种数据类型又是开发时经常要进行声明赋值,特别是一些对一些常见结构体数据大小的计算上,差异还是非常明显的。如下面的数据结构:

struct test {

int i1;

double d;

int i2;

long l;

}

e0da8ffecbc74119e59065a3b19c1fe4.gif

注意这时候的sizeof(test)  在32bit和64bit上是分了不同大小空间的。32bit 上是4+4+4+4+4=20而64bit是8(空半)+8+8(空半)+8=32

Linux 应用兼容64bit/32bit的一些基本原则

1. 声明

如果这个变量在32bit上要求32bit,但是在64bit上要求64bit,应该定义成long型或者如果这个变量指的是一个地址,这里就需要用size_t。

#if __WORDSIZE == 64

#define BASE_ADDRESS 0x00002AB0E7E16000

#else

#define BASE_ADDRESS 0x88000000 /* Approx 2^32 - 2GBytes */

#endif

Unsigned int base_address; // size_t base_address【如果32位,没有问题,在64位就会有问题,这里需要用size_t】

如果有以下这样的转换也不行的,g_shm_mem_ptr 是指针,在32bit可以用int,但到64位需要用long,

if (g_shm_mem_ptr != 0 && (int) g_shm_mem_ptr != -1)改成 if (g_shm_mem_ptr != 0 && (long) g_shm_mem_ptr != -1)

如果这个变量要求分配的空间在不同系统上是一样的,因些对声明long型改成声明int型进行兼容。

typedef union C_data_value

{

int int_data;

char *string_data;

long long_data;//int long_data【32bit long data分配32bit,但是64bit上则分配64bit,为了兼容,需要修改这里数据类型为int】

float float_data;

unsigned int unsigned_int_data;

unsigned long unsigned_long_data;// unsigned int unsigned_int_data;

} C_DATA_VALUE_T;

其它像unsigned long int实际在32位系统就是unsigned long. 取值范围是0~4294967295(232 -1)

/* UINT4 defines a four byte word */

typedef unsigned long //int UINT4;

2. 赋值

不要使用不同类型的变量直接赋值。如

o int 与long 转换32-bits

64-bits

int i;

32bit

32bit

long l ;

32bit

64bit

i =l  ;

OK

Error

o int 与pointer32-bits

64-bits

unsigned int i,* ptr;

32bit

32bit

i=(unsigned)ptr;

OK

Error

*ptr 可以是32bit,但ptr 一定是64bit

o       pointer 与(int *)32-bits

64-bits

int * ptr;

32bit

32bit

int i;

32bit

32bit

ptr =(int *)i;

OK

Error

3. 字符标志位用来表示特定含义

如用0xFFFFFFF 每一个字符位来表示特定含义的用法,需要注意在64位它就变成0x00000000FFFFFFFF,计算时特别要小心。如果要声明0xFFFFFFFFFFFFFF可用long x=-L来声明。

4. 字节序大小头不同

我们知道,字节序分成big-endian 和little-endian. Little-endian 意味着较低内存地址用来存储不重要数据,(所谓不重要数据通常指的是数据的未位,如0x12345678中的5678。big-endian 则相反。如果以内存的排列顺序(从低到高由左向右来看),就会出现高位数据放在前面变成56781234。采用little-endian通常都是intel体系架构主机。

另外,32-bits是两个字节两个字节(16bit)的分配,而64-bits是四个字节(32bit)一次分配。如0x12345678在32bit机器上

0x12345678 big-endian32-bits

64-bits

3

0x78

2

0x56

1

0x34

0x5678

0

0x12

0x1234

0x12345678 little-endian32-bits

64-bits

3

0x12

2

0x34

1

0x56

0x1234

0

0x78

0x5678

在两台不同主机进行数据传输的网络字节序目前采用的是big-endian.

从开发的角度来说,由于glibc库已经实现了内部的封装,大家可以查看以下库文件

/usr/include/bits/endian.h

/usr/include/endian.h

/usr/include/bits/byteswap.h

/usr/include/byteswap.h

我们只要使用与机器无关的函数如ntohl等就可以了。

通常意义上我们都使用函数htonl和ntohl及htons,ntohs进行转换。注意这些函数都不能对64位数据进行转换,

#if __WORDSIZE == 64

#if __BYTE_ORDER == __BIG_ENDIAN

/* The host byte order is the same as network byte order,

so these functions are all just identity. */

#define ntohlong(x) (x)

#define htonlong(x) (x)

#else

#if __BYTE_ORDER == __LITTLE_ENDIAN

#define ntohlong(x) __bswap_64 (x)

#define htonlong(x) __bswap_64 (x)

#endif

#endif

#else

#define ntohlong(x) ntohl (x)

#define htonlong(x) htonl (x)

#endif

#endif

5. 类型重定义

通常一些定义类型有一些跨平台作用,如size_t或者一些明确大小的如int32_t,uint32_t。通常如

int buffersize = (int)sizeof(something);最好的方法是

size_t buffersize = (size_t)sizeof(something)

6. 移位算法

对一些未显示指明类型的常量通常会隐含风险,如12这实际上是int类型。如果long i =12 这实际上是long i =(int)12在32位系统,但在64位系统上long i = (int)12,就会带来问题。

需要声明long i = 1L;;

7. 格式化输出printf

printf()进行格式输出时,不同参数的数据类型在32bit和64 bit下输出结果是完全不一样的。这样的隐藏错误有时很难发现,所以一定要注意检查是否需要修改相应的格式字符串,否则编译器连警告信息都不会出现。

比喻在32bits平台,%d可以打印long也可以是int,但在64位不行,需要使用%ld或者%u

printf("Indx %dld",strtol(tableInfo->tbl_index,NULL,0));

%d和%u的区别

unsigned int dwValue;

printf(“%d”, dwValue);

在dwValue的值大于0x7FFFFFFF时,输出的结果会变成负数。

正确的程序应该为:

printf(“%u”, dwValue);

%x  在32bit用来输出地址,但是在64 上不用,必须用%p

%d在32bit用来输出int and long,在64上不行,必须用%ld

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值