Linux 内核中有很多不同的内部API,头文件和其他支持代码,它们以一种尽可能可移植的方式来抽象和管理硬件平台之间的许多不同.但是硬件可移植不仅仅是linux内核的问题,普通用户应用程序也需要关注自己的字节序.
一.64位兼容
64位到底意味了什么.通常:长整型和指针数据类新使用64位,而其他数据类型可能使用32位.
1.首先遇到的问题是不安全的类型转换
int i=(int)pointer;
如果在64位机器下,pointer是64位长度的.
因此追加了void *类型到c标准中去,由gcc支持:
void *p=pointer
这样可以安全的将一个指针存储在一些通用的类型中.
二.字节序
字节序:一种是最重要的字节优先存储,另一种是最不重要的字节优先存储
数据按内存地址的升序一次存储,高位数据在低地址,就是大头字节序
相反最低位数据放在低地址就是小头字节序
那么字节序到底会导致什么问题呢?
例子:
#include <stdio.h>
#include <stdlib.h>
static inline int little_endian()
{
int endian=1;
return (0==(*(char *)&endian));
}
void broken_endian_example()
{
union
{
int i;
char j[sizeof(int)];
}test={0xdeadbeef};
int i=0;
for(i=0;i<sizeof(int);i++)
{
printf("test.h[%d]=0x%x\n",i,test.j[i]);
}
}
int main(int argc,char **argv)
{
printf("this machine is ");
little_endian()?printf("big"):printf("little");
printf("endian\n");
printf("this program was build on a machine that is :");
#if BYTE_ORDER==BIG_ENDIAN
printf("big endian\n");
#else
#if BYTE_ORDER==LITTLE_ENDIAN
printf("little endian\n");
#else
printf("something weird\n");
#endif
#endif
printf("and here is a silly example...\n");
broken_endian_example();
exit(0);
}
执行完:
this machine is little endian
this program was build on a machine that is :little endian
and here is a silly example...
test.h[0]=0xffffffef
test.h[1]=0xffffffbe
test.h[2]=0xffffffad
test.h[3]=0xffffffde
X86体系用小端字节序,即 低内存地址空间存储数据的低位。
现代计算机通常优化了内存访问粒度.如果你试图读取一个字节的数据,处理器实际上执行了一个完整的32位操作,并将结果截断以返回你要的字节.所以在开发中需要小心指针运算以及类型转换是否映像程序的运行.为了实现透明的可移植,可以使用gnu自动话工具测试以实现函数的自动替换.