参与运算的寄存器的数据长度,另一种说法是CPU一次处理的数据宽度,并不是指总线宽度。CPU能同时处理二进制数的位数是多少位,就称其是多少位的计算机。也有数据总线的位数是CPU位数的一半的情况,就称其是准多少位的计算机。比如CPU是16位,数据总线也是16位,则是16位计算机;CPU是16位,数据总线也是8位,则是准16位计算机。像51单片机的地址总线是16位的,但是它是8位机。像ARM的存储器也有八位的,但是它是32位机。而是指CPU处理的数据的宽度,也就是CPU一次数据的吞吐量。比如同一条指令:MOV R0 R2在51单片机里面,R0和R2都是8位的,所以51的CPU一次只能处理8位数据。在ARM里面,R0和R2是32位的,所以ARM的CPU一次能处理32位数据。这就是区别。
速度上有区别,取决于CPU、寄存器的字长。8位单片机不能直接处理16位数据,要按照8位数据来处理,要分几个过程来完成。而16位单片机,可直接处理16们数据,因为其ALU,寄存器等都是16位的,可一次完成8位单片机要多步完成的动作,特别是对于数据处理,16位单片机有它的优势。而且16位单片机大多数据接口都为16位。
原来是16位单片机想改用8位的替代是可以的,但电路及程序都要做相应改变,并且改为8位机后,在功能和速度上要能够满足你工作的需要才行。
1、一些基本类型位宽变化了,还有一些类型位宽不确定,比如说int,相信99%的32位编译器(未作统计)都将int视为32位有符号型,但在64位编译器上,这点是不确定的,ms的编译器,int型都还是32位有符号整型,但印象中存在某个平台的gcc编译器将int位宽增加到64位。诸如此类,需要特别注意
2、强制类型转换代码需特别注意,特别是c开发人员,对于指针和整型的理解已炉火纯青,借由整型空间存储指针的方法是很常用的(也是很方便的),由于强制转换代码的存在,编译器并不会提示诸如64位到32位转换中可能的信息损失,这也就导致了运行时可能的问题爆发。这一点需要特别注意,严查代码各处的强制转换。
3、模块间调用,严格说这一点还是由位宽变化导致的,做法还是需要筛查类型是否匹配的问题
留心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;
% ccwarning: 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.
留心unionunion中的成员,必须保持平衡,也就是说,必须保证大小相等才有意义,所以移植时也要注意。例如: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必须够长。
留心sizeofsizeof返回类型为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同样适用。
本文来源:https://www.2haoxitong.net/k/doc/c0ea8d41b90d6c85ed3ac669.html
文档为doc格式