概述
为了缩短开发过程、降低开发成本,我们提倡软件复用。软件复用中常见的一个场景就是在不同产品或平台上使用同一套代码。这里就引入一个软件可移植性的概念。广义上来说,软件的可移植性是指软件从某一环境转移到另一环境下的难易程度。这里的环境可能是不同的硬件、软件……
在本文中,可移植性特指从C语言角度而言,具体是指同一功能的C语言程序代码从某一平台(设备)移植到其他平台(设备)上时,为了保证其代码正常运行而需要进行修改的难易程度。良好的移植性需要满足以下两点
- 代码不需要修改,只需重新编译
- 程序可以正确运行
数据长度
概念
C语言中short、int、long等被称为基本数据类型,它们的长度在不同的平台间是不确定的,因此它们不具备可移植性。大多数现代机器都有8位字符,但有些有7位或9位字符。long通常至少为32位长,因此可以使用长整数来表示文件的大小。int通常至少为16位长,因为较短的整数会对数组的最大大小施加太多限制。short几乎总是16位。
不同平台对相同的类型长度可能有不同的定义,如下表所示
type |
32 bit |
64 bit(Linux) |
64 bit(Win64, MinGW-w64) |
sizeof(int) |
4 bytes |
4 bytes |
4 bytes |
sizeof(long) |
4 bytes |
8 bytes |
4 bytes |
sizeof(int*) |
4 bytes |
8 bytes |
8 bytes |
为了解决相同类型在不同平台长度不同的问题,各个平台中都会定义类似int32_t,int16_t这样的数据类型,他们都是不同的整型,但是长度是固定的,这是他们被称为可移植性数据类型的原因。他们的实现原理如下,比如在A平台中int是4字节的,那么A平台的int32_t是这么定义的:
typedef int int32_t; |
在B平台中,long long是4字节的,因此B平台的int32_t就是这么定义的:
typedef long long int32_t; |
这样就保证了不管用户程序在哪个平台运行,只要定义了int32_t的数据类型,就一定是4个字节的了。
问题说明
关于数据长度最常见的问题之一就是忽视了其在不同平台上的差异性。如下代码所示,该代码在64位平台上运行就会出错
void memcpy_unalign(unsigned char *dest, unsigned char *src, uint len) { unaligned_ul *s, *d; int size;
s = (unaligned_ul *)src; d = (unaligned_ul *)dest; size = (int)len; while (size > 0) { *d = *s; size -= 4; <- 这里大小只减去了4 s++; <- 指针++操作移动了8个字节 d++; } } |