c/c++ 32/64位兼容编程

说明

  • 在工作中,使用到的平台较多,交叉编译工具链有32位的也有64位的。
  • 所谓32位/64位是硬件层次的概念,是指处理单元的三大总线(数据总线,控制总线,地址总线)是32根导线还是64根导线,每一根导线可以传输1位数据,所以是32位和64位,64位的cpu可以在软件层次兼容32位程序,安装32位系统也能跑32位程序,但是32位的cpu当前无法兼容64位的程序,理论上软件也能实现兼容,但是好像没有必要性。
  • 编程方面,希望程序能够兼容32位和64位,这样换平台只需要重新编译就好了,不需要进行修改,节省工作量,也方便代码维护。

数据模型

  • 硬件层次,32位cpu可以一次读取32位数据,64位cpu可以一次读取64位数据,但是软件层次,会有很多种需求,例如:一次读取1个字节数据,一次读取2个字节的数据等,为了满足多样的需求,编程语言需要提供给用户一个数据模型,即:a 对应 1个字节的数据,b 对应的 2的字节的数据,还是 a 对应 2 个字节的数据,b对应3个字节的数据。
  • 理所应当,该数据模型需要足够通用,并且能满足用户的所有需求,由于硬件的性质,二进制就非常合适,所以大部分数据类型都是呈2的倍数关系。
  • 数据模型是软件概念,硬件每一次读取依然是32位/64位,软件再取其中的相应位数。

32位数据模型 (ILP32)和64位数据模型(LP64)

  • 32位数据模型和64位数据模型是不同的。
  • C语言在32位cpu下使用32位数据模型ILP32,"ILP32"的意思是32位数据模型int、long、指针(p)都是32位的。LP64类似,表示C语言在64位cpu环境下的数据模型是LP64,此时的long和指针已为64位。
  • 基础数据类型
数据类型数据长度(32位环境)数据长度(64位环境)是否signed
char88Y
short1616Y
int3232Y
long3264Y
long long6464Y
point3264N
size_t3264N
ssize_t3264Y
off_t3264Y
  • 以上表格不需要死记硬背,需要理解
  1. 数据模型是为了满足软件层次的需求设计的,因此不管是多少位环境,char永远是8位,short永远是16位,int永远是32位,不会缺失。
  2. 数据模型中几乎所有数据类型都小于硬件位数,例如:32位模型,都小于32或等于32位,64位模型中的数据类型都小于64位,是因为希望所有数据类型都小于一次硬件读取单元,32位模型的long long是一个特例,是后面由于软件新需求(64单元)而添加的。
  3. 基础的数据类型(char,short,int,long)是倍数关系,直至顶,而size_t,off_t 是软件需求触发的数据类型(size_t :个数,off_t : 偏移)为了足够满足软件需求,数据类型长度按最大值分配(硬件读取单元长度)。

数据模型设置

  • 由于数据模型是软件概念,因此在编译时可以手动设置应用的模型,默认匹配系统。
  • gcc 设置如下:
m32指定编译为32位应用程序;
make CFLAGS=-m32
m64指定编译为64位应用程序;
make CFLAGS=-m64

变长数据模型导致的问题

  • 不同数据模型下数据类型的长度不固定可能会导致很多奇怪的问题,编程时需要特别注意,例如:
  1. 打印问题(size_t)
  • size_t的数据长度 32/64位环境上是不同的,打印时无法使用‘ld’或’d’等。
size_t val = xxx;
printf("%zu",val);
  1. 数据截断问题
  • 64位环境下,size_t赋值给int类型就可能发生数据截断。
  1. 结构体内存对齐问题
  • 结构体中变量长度在不同环境下发生变化,内存对齐可能会发生改变。

定长数据类型

  • 32/64位环境下,不同数据类型的长度可能不同,但是有时候会存在这样的需求,在不同环境变量的数据长度需要一致,特别是网络传输中,这就是定长数据类型,例如:uint64_t, uint32_t 等。

定长数据出现的问题

  1. uint64_t/int64_t 打印
  • 在32位环境下表示64位数据需要使用long long int,打印格式为%lld,而64位环境只需要使用long int,打印格式为%ld,定长数据类型(uint64_t/int64_t)为了兼容打印时采用PRId64/PRIu64宏,如下:
#include <inttypes.h>
uint64_t num=10;
printf("uint64: %" PRIu64 "\n", num);
int64_t num1=10;
printf("int64_t: %"PRId64"\n", num1);
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值