32位機與64位機資料型別
最近在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 位的帶符號整數。