最近在Linux下移植程序时遇到了一个问题,将32位机下的程序移植到64位上,在用long型读入文件时发生了错误,读出来的是0,后经测试原来是在32位机下和64机下某些数据类型表示的不一样。测试程序如下:
#include <stdio.h>
int main ()
{
printf ("char /n", sizeof(char));
printf ("short /n", sizeof(short));
printf ("int /n", sizeof(int));
printf ("long /n", sizeof(long));
printf ("long long/n", sizeof(long long));
printf ("float /n", sizeof(float));
printf ("double /n", sizeof(double));
printf ("long double /n", sizeof(long double));
printf ("pointer /n", sizeof(void*));
return 0;
}
在Windows下,是这样的结果
WinXP 32 x64 |
而在Linux下面,却是另一个结果
Linux x86 amd64 |
由此可见,在移植程序时,要特别注意long,long double和pointer指针类型的使用。
数据在内存中存储的方法也不一样:
Little-endian 是将低位字节存储在内存的低地址中,将高位字节存储在内存的高地址中。
Big-endian 是将高位字节存储在内存的低地址中,将低位字节存储在内存的高地址中。
表 3. 64 位 long int 类型的布局
| 低地址 |
|
|
|
|
|
| 高地址 |
Little endian | Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
Big endian | Byte 7 | Byte 6 | Byte 5 | Byte 4 | Byte 3 | Byte 2 | Byte 1 | Byte 0 |
例如,32 位的字 0x12345678 在 big endian 机器上的布局如下:
最近在Linux下移植程序时遇到了一个问题,将32位机下的程序移植到64位上,在用long型读入文件时发生了错误,读出来的是0,后经测试原来是在32位机下和64机下某些数据类型表示的不一样。测试程序如下:
在Windows下,是这样的结果
而在Linux下面,却是另一个结果
由此可见,在移植程序时,要特别注意long,long double和pointer指针类型的使用。
数据在内存中存储的方法也不一样: Little-endian 是将低位字节存储在内存的低地址中,将高位字节存储在内存的高地址中。 Big-endian 是将高位字节存储在内存的低地址中,将低位字节存储在内存的高地址中。 表 3. 64 位 long int 类型的布局
例如,32 位的字 0x12345678 在 big endian 机器上的布局如下:
如果将 0x12345678 当作两个半字来看待,分别是 0x1234 和 0x5678,那么就会看到在 big endian 机器上是下面的情况:
然而,在 little endian 机器上,字 0x12345678 的布局如下所示:
类似地,两个半字 0x1234 和 0x5678 如下所示:
|
从 32 位迁移到 64 位时,增长的主要类型是指针和派生数据类型,如句柄。在 Windows 64 位中,目前的指针和派生类型是 64位 long 类型。大小增加的其他一些类型还有:WPARAM、LPARAM、LRESULT 和 SIZE_T。其中一个原因是,它们作为参数使用,并且某些函数将指针作为参数使用。
从“int”和“long”派生出的所有类型的大小仍然是 32 位,其中包括 DWORD、UINT 和 ULONG。小于 32 位的类型保留它们当前的大小。一个示例就是“short”数据类型,它仍然保留为 16 位的带符号整数。