多數情況下,編寫完全可移植的程式碼是不可能的。因為同樣的資料類型在不同的編譯環境下所產生的結果(OBJ代碼)可能是不同的,特別是針對嵌入式系統,不同的運行平台可能要求不同的代碼來實現它所要求的獨特功能。為了增加程式碼可移植到多個平台的可行性,比較好的方法是提供一個可移植的資料或功能介面,讓那些移植的部分隱藏在這些介面之後,當然,這樣的事情應該全部是系統設計的工作。下面介紹有關可移植性編程的一些常規做法:
1、資料大小或長度相關性 C程式庫所提供的“sizeof()”函數是一個很好的可移植的功能介面範例,對於不同的嵌入式系統的編譯環境或平台,某些資料類型的大小或長度被解析成不一樣的結果,而在程式體中,對這些資料類型的訪問有十分嚴格的要求。所以在這種情況下,對這些資料類型的定義必須考慮到在不同環境的共用,也就是說,資料類型的定義將成為可移植的資料介面。例如,程式中可能有對8位、16位和32位的整數類型資料的訪問的要求,為了增加程式碼的可移植性,慣常的做法是把這些整數以全域類型定義在某個H標頭檔中。例如:
typedef signed char INT8;typedef unsigned char UINT8;typedef signed int INT16;typedef unsigned int UINT16;typedef signed long INT32;typedef unsigned long UINT32; 2、位元組位序 不同的CPU,例如PowerPC和Inter X86系列,對於位元組順序的解析是完全相反的。也就是說,對於高位元組在前面還是低位元組在前面,它們的處理方法是截然不同的。這是又CPU內部寄存器的儲存和訪問機制決定的,也就是我們常說的大端模式和小端模式。這樣的特點對程式中的位元組和位操作將會有相當大的影響,所以可移植性編程應該將涉及位操作的程式設計成僅僅與固定的位序相關,變數或類型同樣也定義成與CPU相關的資料介面,例如:typedef struct{#if LittleEndian word hiword; word loword;#else word
loword; word hiword;#endif} DWord; 3、位操作 在嵌入式系統開發中,基於儲存空間的限制,我們經常利用位來表示某些裝置或操作的狀態,也就是說,位操作是一種使用十分頻繁並高效的操作。同樣位序也和CPU相關,所以習慣上將位的定位定義為一些宏,從而提高它們的可移植性。例如:#define BYTE_BIT0 0x01 #define BYTE_BIT1 0x02#define BYTE_BIT2 0x04#define BYTE_BIT3 0x08#define BYTE_BIT4 0x10#define BYTE_BIT5 0x20#define BYTE_BIT6 0x40#define BYTE_BIT7 0x80
4、對齊 對齊同樣與CPU緊密相關,有些微處理器定義和要求嚴格的8位、16位或32位對齊,也就是說,對儲存地址的訪問或資料的讀寫必須以8位、16位或32位方式對齊,這樣可能產生誤操作,從而導致系統的不穩定或崩潰。因此,在可移植性編程中,應該對涉及此類操作的函數定義為可移植的介面函數。