Tuesday, March 20, 2007

C++的 #pragma pack(n) - 位元組對齊 or 字節對齊

這東西的中文名稱似乎沒有統一,我也是第一次看到。

今天學弟在 C++Builder 下嘗試要把已有的 BITMAPINFO, 以及 Bitmap 的影像陣列儲存到 bmp 格式的檔案中,我看了看覺得,既然已經有 BITMAPINOF 跟 DIB 格式的影像陣列,那不如直接用 ofstream::write 寫進檔案裡。但是試了好久,卻一直無法輸出正確的檔案。

問了一下 Google 大神,馬上找到一篇

http://topic.csdn.net/t/20020402/07/615811.html


不過文中所說的方法必須要修改 C++Builder 內建的檔案,因為擔心會有後遺症,所以我決定自己寫 BITMAPINFO, BITMAPFILEHEADER, BITMAPINFOHEADER 來處理,但是對齊的問題我也會遇到。對齊的概念及會產生的問題請參考 字節對齊 以及 請問C 裡面的 #pragma 這兩篇文章。

32Bits 系統預設是 #pragma pack(4) ,而 BITMAPFILEHEADER 這個結構的長度為 14 Bytes,為了達到預設對齊的結果,編譯器會將 BITMAPFILEHEADER 的長度拉長成 16 Bytes (4 的倍數),造成輸出的檔案的標頭檔會有問題,無法被讀圖軟體解析。為了避免這個問題,必須在宣告結構之前,將位元組對齊重設為 2 ︰
#pragma pack(2)
而在宣告結束後,重設為預設值︰
#pragma pack()
=> 在 pack() 的括號中不給值,即會重設回預設值。

如此一來,由於 14 為 2 的倍數,因此 BITMAPFILEHEADER 的結構就不會再受到影響。