使用Intel編譯器解決位元組序問題

2021-06-03 13:05:43 字數 2206 閱讀 7237

使用intel編譯器解決位元組序問題

1.       什麼是位元組序(endianess)

endian或者endianess, 一般指的是在外部記憶體中儲存的位元組順序。在ia平台上開發網路程式的程式設計師大多遇到過位元組序問題。網路協議是按照大端位元組序定義的, 我們通常稱之為big-endian, 簡稱大端。 ia架構的主機位元組序是小端位元組序, 我們稱之為little-endian, 簡稱小端。在主機上定義的資料比如ip位址在傳送到網路端的時候, 通常需要做位元組序的轉換, 也就是小端到大端的轉換, 比如使用hton()來實現。

大端和小端在外部記憶體中存放的位元組序是相反的。 對於大端來說, 在記憶體低位址存放的是資料高位位元組,在記憶體高位址存放的是資料低位位元組。 小端則相反, 在記憶體低位址存放的是資料低位位元組, 在記憶體高位位址存放的是資料高位位元組。

舉例來說, 對於整數0x89abcdef在記憶體中的存放, 大端和小端區別如下圖所示:

2.       大小端帶來的程式移植問題

對於不同的主機架構, 支援的位元組序也不一樣。 對於英特爾的架構來說, 基本都是小端架構的。其他的比如sun sparc, ibm ppc, 使用的是大端架構。如此一來, 針對某個架構開發的應用程式, 當我們要把它移植到其他不同位元組序的架構上時, 就存在乙個位元組序的問題。 雖然同樣是c/c++的**, 同樣一段程式, 在大端架構上執行得到的結果和小端架構上執行得到的結果可能是不一樣的。

舉個簡單的例子, 程式foo.c

#include

int a = 0x12345678;                                    

int main()

上面程式中對整數a取位址後強制轉換為位元組指標, 然後把位元組指標指向的位元組列印出來。我們可以使用gcc來編譯該程式, 無論大端還是小端平台, 使用命令gcc foo.c 編譯該程式。

在這個例子中, 在大端架構中, &a位址低位存放的是資料高位位元組, 也就是0x12, 所以列印出來的值是0x12。 但是在小端架構中, 列印出來的資料值就是0x78了。 這樣就導致了在不同的位元組序平台上程式執行結果不一致, 從而出現程式的邏輯錯誤。

類似的例子有很多, 我們可以自己思考一下, 羅列一些在大小端平台上執行結果不一致的情況。

對於很多針對sparc 或者ppc開發的應用程式來說, 如果想把它移植到ia平台上, 位元組序問題就是我們不得不考慮的乙個問題。 特別是對一些傳統的**, **量大, 動則百萬行, 千萬行數量級的**, 如果手工去修改這樣的**, 帶來的工作量是相當巨大的。

3.       解決方案

針對位元組序問題, 解決方案主要有2種, 手工修改**和使用工具。

1.       手工修改。 該方案需要程式設計師掃瞄所有程式中可能出現位元組序問題的地方, 逐點修改**。 如果**量小, 比如幾千行的**, 手工修改不失為乙個較好的選擇。 對於**量大的情況, 手工修改工作量巨大, 位元組問題定位困難, 容易產生遺漏, 除錯難度高。 位元組序的問題通常導致的是程式的邏輯錯誤, 一般都是執行時出錯, 這樣的問題對程式的除錯帶來不小的難度。

2.       使用intel c/c++ compiler with bi-endian technology來實現自動的位元組序轉換。

使用intel編譯器可以實現位元組序的自動轉換。 該編譯器的實現大大節省了程式移植的難度, 極大的縮短了程式移植的工作量, 節省了程式移植的時間, 可以很快的幫助程式設計師移植大批量的**到intel平台上。對於百萬或者千萬行數量級的**移植來說, 使用intel編譯器來實現**的移植顯然是乙個最佳選擇。

intel編譯器提供了很多種手段來幫助程式設計師實現**的移植, 對位元組序的控制從粗粒度的檔案編譯, 到細粒度的變數位元組序, 均提供了很好的支援。 針對本文中提到的例子foo.c來說, 簡單的用intel編譯器來編譯: icc foo.c –big-endian

這樣程式執行的結果就可以和期望的大端平台上執行結果完全一致。

intel編譯器針對位元組序的支援內容有很多, 這裡就不一一細述。 有興趣的朋友可以跟我們聯絡。

相同程式在大端和小端平台上執行結果不一致的情況有很多, 有興趣的朋友可以**一下。 這裡再舉個例子:

unsigned char a[2] = ;

short x;

x=*(short*)a;

上面x的值在大端平台上和小端平台上值分別是什麼呢?

大小端平台執行行為不一致的情況, 你還可以舉出多少其他型別的例子呢?

intel編譯器編譯cp2k

編譯cp2k記錄 所遇到問題 mkl版本問題 intel paralell composer xe 2011版本編譯出錯,在鏈結過程中某些函式缺失 而intel paralell composer xe 2013 mkl中不帶 scalapack,直到安裝2015版才解決這個問題 元件cp2k 原始...

編譯器與位元組對齊

編譯器版本 gcc 4.1.2 vc 6.0 上次研究了結構體和位元組對齊的問題,不過有個復合結構體有點奇怪。pragma pack 8 struct s1 struct s2 pragma pack 在gcc下,sizeof struct s2 20,但在vc 6.0下卻是24 其實,這個牽扯到了...

Intel和GNU編譯器對OpenMP的支援情況

3 文獻 intel和gnu的編譯器均實現了對openmp api的支援,這裡列出各代編譯器對openmp標準的支援情況,方便使用openmp的各種特性。以下內容 於openmp api specification,這裡也僅粗略給出最常見的 商intel和開源社群gnu對openmp標準的支援,且大...