stucture word alignment

參考 google 上找到的新聞群組資料。
最近在看 hostapd 中的程式碼時,有看到 stucture 的定義之後,有跟著 __attribute__ ((packed)) 的符號,上網查了之後,才知道那是用來解決 struture word alignment 問題的 gcc extension.

struct alignment 是指 struct 中的資料 compiler 會自動加入一些 padding 的字元,讓整個 struct 的大小會是 4byte 的倍數,有些 cpu 允許資料沒有 padding,像是 x86 cpu 就可以,而有些不行,但是在網路傳輸資料的時候,是不能加入這個 padding 字元的,會造網路連線另一端解釋宇元的時候,發生錯誤。所以會使用 GNU compiler extension 的 __attribute__ ((packed)) 符號,讓 compiler 不要加入 padding 字元

新聞群組的文章如下:
第 1 條留言
寄件者:yorkwu@ms4.hinet.net (yorkwu@ms4.hinet.net)
主旨:壓緊結構(pack struct)的問題.
網上論壇:tw.bbs.comp.language
日期:1998/03/21

 有些檔案格式的結構不是對齊 4 byte 位置的, 這時compiler
 可能會多填一些東西讓它對齊, 可是這樣會讓檔案錯亂.
 例如 Windows 下的 BMP 檔. 請問如果我用 gcc, 如何讓它不會
 寫出錯誤情型呢? 希望能儘量用 compiler option, 不要改程式.
 多謝各位大大指教...

--
 o=|====>   yorkwu@ms4.hinet.net


第 2 條留言
寄件者:Steve Lee (chlee@stevel.dyn.ml.org)
主旨:Re: 壓緊結構(pack struct)的問題.
網上論壇:tw.bbs.comp.language
日期:1998/03/23

yorkwu@ms4.hinet.net wrote:
:  有些檔案格式的結構不是對齊 4 byte 位置的, 這時compiler
:  可能會多填一些東西讓它對齊, 可是這樣會讓檔案錯亂.
:  例如 Windows 下的 BMP 檔. 請問如果我用 gcc, 如何讓它不會
:  寫出錯誤情型呢? 希望能儘量用 compiler option, 不要改程式.

以前有人提到過:

struct {
 .....
} __attribute__ ((packed)); 
-- 
Steve, Chia-Huan Lee/李嘉桓
(建中49屆,台大電機101級)
chlee@ck.tp.edu.tw


第 3 條留言
寄件者:紅塵多少奇才 (smhwang.bbs@csie.nctu.edu.tw)
主旨:Re: 壓緊結構(pack struct)的問題.
網上論壇:tw.bbs.comp.language
日期:1998/03/23

小弟也遇過這種問題, 後來我放棄 struct, 改用 #define
例如 .bmp 的檔頭, 先算出每個欄位的 offset

#define bfType      0
#define bfSize      2
#define bfReserved1 6
#define bfReserved2 8
#define bfOffBits   10

假設現在檔頭存在 m 所指的位址(m 須為 char *), 則

type = *((WORD *)(m+bfType));
size = *((DWORD *)(m+bfSize));

-----------------------------------------------------------

第 1 條留言
寄件者:小魚 (ChungLin.bbs@wd.atc.ntut.edu.tw)
主旨:Re: [問題] 奇怪的問題!?
網上論壇:tw.bbs.admin.installbbs
日期:1999/12/13

※ 引述《stevel@bbs.ee.ntu.edu.tw (1s軌域之逆旋水子)》之銘言:
: ※引述《ChungLin.bbs@wd.atc.ntut.edu.tw (小魚)》之銘言:
: 能不能請教一下,你怎麼用 sizeof 來算出 "256" bytes 的?

    只要用 " // " 將以下的幾行拿掉就可以算出來了...
: 如果我上面累計 byte 數沒數錯的話,sizeof(userec)應為 510,
: 510-246-4-4=256,就是這樣來的嗎?
    這點我也覺得奇怪...整體上遺失了 4bytes ...
    如果將上面全用 sizeof 算出 來確實是 512 bytes ...
    但事實上應該只有 508 bytes 才對...
: :    如果以 sizeof 來看 struct 的話 month,day,year 應該寫入在 254,255,256
: :    byte 的地方才對...但以 HEX 看 .PASSWDS 卻是寫入在 252,253,254 byte
: :    的地方 ...真是難以理解...那 255,256 到底從哪跑出來的呢?
: 我只知道 usint exmailbox 那裡,會有 alignment 的問題,
: 空了 2 byte 出來。
:     257 258 259 260 261 262 263 264 265
:    | p | i |padding|    exmailbox  | padding...

    但在 PASSWDS 裡它是 257 258 259 260 261 262 263 264 265
                       |sex|sta| p | i | exmailbox     | pad....
    並沒有以上情況說....


--
 [1;36m※Post by  [37mChungLin       [36mfrom  [33m210.242.86.141           [m
 [1;34m▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂ [m
    [1;36m風與塵埃的對話 [31m˙ [33m電子佈告欄系統 [31m˙ [32mwd.twbbs.org [31m˙ [37m140.124.201.23 [m
 [1;34m▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ [m


第 2 條留言
寄件者:一生一世 (lasehu.bbs@bbs.nsysu.edu.tw)
主旨:Re: [問題] 奇怪的問題!?
網上論壇:tw.bbs.admin.installbbs
日期:1999/12/14

==> ChungLin.bbs@wd.atc.ntut.edu.tw (小魚) 的文章中提到:
>※ 引述《stevel@bbs.ee.ntu.edu.tw (1s軌域之逆旋水子)》之銘言:
>: ※引述《ChungLin.bbs@wd.atc.ntut.edu.tw (小魚)》之銘言:
>: 能不能請教一下,你怎麼用 sizeof 來算出 "256" bytes 的? 只要用 " // " 將以下的幾行拿掉就可以算出來了...
>: 如果我上面累計 byte 數沒數錯的話,sizeof(userec)應為 510,
>: 510-246-4-4=256,就是這樣來的嗎?
>    這點我也覺得奇怪...整體上遺失了 4bytes ...
>    如果將上面全用 sizeof 算出 來確實是 512 bytes ...
>    但事實上應該只有 508 bytes 才對...
>: 我只知道 usint exmailbox 那裡,會有 alignment 的問題,
>: 空了 2 byte 出來。
>:     257 258 259 260 261 262 263 264 265
>:    | p | i |padding|    exmailbox  | padding...
>    但在 PASSWDS 裡它是 257 258 259 260 261 262 263 264 265
>                       |sex|sta| p | i | exmailbox     | pad....
>    並沒有以上情況說....

  這就是 word alignment, 

  char email[50];               /* 50 bytes */
  char address[50];             /* 50 bytes */
  char justify[REGLEN + 1];     /* 39 bytes */
  uschar month;                 /* 1 byte  */  
                              --> 到此剛好是   252 bytes = (252/4=63) words
  uschar day;                   /* 1 byte  */
  uschar year;                  /* 1 byte  */ -->到此應該是254 bytes 才對,
  uschar sex;                   /* 1 byte  */    但如果用 sizeof 來算卻是
  uschar state;                 /* 1 byte  */    256 bytes ...好奇怪..
                              ---> 63+1=64 words
  uschar pager;                 /* 1 bytes */
  uschar invisible;             /* 1 bytes */   
                              ======================> 這裡有 2 bytes unused
                                                      因為 word alignment
                              ---> 64+1=65 words 
  usint  exmailbox;             /* 4 bytes */
                              ---> 65+1=66 words
  char pad[246];                 /* 246 bytes */
                              66+(246/4=62)=128 words = (128*4=512) bytes

  

--
lasehu@cc.nsysu.edu.tw.NOSPAM
 [m
--
* Origin: 中山大學-美麗之島BBS * From: 140.117.12.64 [已通過認證]


第 3 條留言
寄件者:1s軌域之逆旋水子 (stevel@bbs.ee.ntu.edu.tw)
主旨:Re: [問題] 奇怪的問題!?
網上論壇:tw.bbs.admin.installbbs
日期:1999/12/16

※ 引述《ChungLin.bbs@wd.atc.ntut.edu.tw (小魚)》之銘言:
: ※ 引述《stevel@bbs.ee.ntu.edu.tw (1s軌域之逆旋水子)》之銘言:
: : ※引述《ChungLin.bbs@wd.atc.ntut.edu.tw (小魚)》之銘言:
: : 能不能請教一下,你怎麼用 sizeof 來算出 "256" bytes 的?  只要用 " // " 將以下的幾行拿掉就可以算出來了...
: : 如果我上面累計 byte 數沒數錯的話,sizeof(userec)應為 510,
: : 510-246-4-4=256,就是這樣來的嗎?
:     這點我也覺得奇怪...整體上遺失了 4bytes ...
:     如果將上面全用 sizeof 算出 來確實是 512 bytes ...
:     但事實上應該只有 508 bytes 才對...
: : 我只知道 usint exmailbox 那裡,會有 alignment 的問題,
: : 空了 2 byte 出來。
: :     257 258 259 260 261 262 263 264 265
: :    | p | i |padding|    exmailbox  | padding...
:     但在 PASSWDS 裡它是 257 258 259 260 261 262 263 264 265
:                        |sex|sta| p | i | exmailbox     | pad....
:     並沒有以上情況說....

看了 lasehu 所說,我才知道我漏了最後頭的 padding。

不過並非不能要求 compiler 在 alignment 方面改變一下,
例如下面這樣,就不會有 padding,這是 gcc 的 extension。

  struct userec {
      ....
  } __attribute__ ((packed));


解決 alignment 的問題,最好還是自己把 structure 裡頭的
member 調一調。像是 exmailbox 可以調到 pager 前面,pad 陣列
變成 248 chars 等等。
--
 [m※ Origin: 臺大電機 Maxwell 站 ◆ From: localhost



-----------------------------------------------------
第 1 條留言
寄件者:elite (elite.bbs@cis.nctu.edu.tw)
主旨:結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/19

請問底下的結構長度?
struct stocknp
{
  char name[11];
  int vol;
  float open;
  float high;
  float low;
  float close;
};

環境是在 pentium linux下
--
 * Origin: ★ 交通大學資訊科學系 BBS ★ <bbs .cis.nctu.edu.tw: 140.113.23.3>


第 2 條留言
寄件者:新系統有問題嗎 ? (TerryLiaw.bbs@Terry.Dorm10.NCTU.edu.tw)
主旨:Re: 結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/19

※ 引述《elite.bbs@cis.nctu.edu.tw (elite)》之銘言:
: 請問底下的結構長度?
: struct stocknp

plz use sizeof(stockup)
--
以下程式選自The International Obfuscated C Code Contest 1984 年作品
int i;main(){for(;i["]<i ;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}

--
※ Origin: 克萊恩大地 ◆ From: Terry.Dorm10.NCTU.edu.tw
--
Origin: 克萊恩大地 Terry.Dorm10.NCTU.edu.tw (140.113.122.99)


第 3 條留言
寄件者:雜毛老道藏鏡人 (AlbertB.bbs@BirdNest.AceArt.Net)
主旨:Re: 結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/19

※ 引述《TerryLiaw.bbs@Terry.Dorm10.NCTU.edu.tw (新系統有問題嗎 ?)》之銘言:
: ※ 引述《elite.bbs@cis.nctu.edu.tw (elite)》之銘言:
: : 請問底下的結構長度?
: : struct stocknp
: plz use sizeof(stockup)

考慮一下alignment,我想它的意思可能是這個.

--
※ Origin: 鳥窩 (BirdNest.AceArt.Net) ◆ From: abwang.abit.com.tw


第 4 條留言
寄件者:elite (elite.bbs@cis.nctu.edu.tw)
主旨:Re: 結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/19

==> 在 AlbertB.bbs@BirdNest.AceArt.Net (雜毛老道藏鏡 的文章中提到:
> ※ 引述《TerryLiaw.bbs@Terry.Dorm10.NCTU.edu.tw (新系統有問題嗎 ?)》之銘言:
> : plz use sizeof(stockup)
> 考慮一下alignment,我想它的意思可能是這個.
若照我的原意,結構長度應該為31 bytes
struct stocknp
{
  char name[11];        11 bytes
  int vol;               4
  float open;            4
  float high;            4
  float low;             4
  float close;           4
};

但是以sizeof(stocknp)後卻是32 bytes
我的資料恰是上面的結構且是31 bytes
但若以read讀資料進來,那存取到的
vol、open、high鐵錯!
gcc 有無辦法去取消這種alignment?
--
 * Origin: ★ 交通大學資訊科學系 BBS ★ <bbs .cis.nctu.edu.tw: 140.113.23.3>


第 5 條留言
寄件者:雜毛老道藏鏡人 (AlbertB.bbs@BirdNest.AceArt.Net)
主旨:Re: 結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/19

※ 引述《elite.bbs@cis.nctu.edu.tw (elite)》之銘言:
: ==> 在 AlbertB.bbs@BirdNest.AceArt.Net (雜毛老道藏鏡 的文章中提到:
: > 考慮一下alignment,我想它的意思可能是這個.
: 若照我的原意,結構長度應該為31 bytes
: struct stocknp
: {
:   char name[11];        11 bytes
:   int vol;               4
:   float open;            4
:   float high;            4
:   float low;             4
:   float close;           4
: };
: 但是以sizeof(stocknp)後卻是32 bytes
: 我的資料恰是上面的結構且是31 bytes
: 但若以read讀資料進來,那存取到的
: vol、open、high鐵錯!

鐵錯是未必啦,如果你都乖乖的用指標,不要自己用byte-level
存取,應該是不會出錯的.

Pentium上面資料是一定要alignment的,所以name那邊大概
留了12byte,剛好湊滿32 bit邊界.

: gcc 有無辦法去取消這種alignment?

可能性不大,這是machine dependence的問題.

--
※ Origin: 鳥窩 (BirdNest.AceArt.Net) ◆ From: 203.73.138.7


第 6 條留言
寄件者:elite (elite.bbs@cis.nctu.edu.tw)
主旨:Re: 結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/19

==> 在 AlbertB.bbs@BirdNest.AceArt.Net (雜毛老道藏鏡 的文章中提到:
> 鐵錯是未必啦,如果你都乖乖的用指標,不要自己用byte-level
> 存取,應該是不會出錯的.
  結果真的是錯了,因為我的source資料是外來的,並非結構自己產生的!

> Pentium上面資料是一定要alignment的,所以name那邊大概
> 留了12byte,剛好湊滿32 bit邊界.
> : gcc 有無辦法去取消這種alignment?
> 可能性不大,這是machine dependence的問題.
  是machine dependence 還是compiler dependence?
  因這資料我猜是VB寫出來的,所以懷疑!
--
 * Origin: ★ 交通大學資訊科學系 BBS ★ </bbs><bbs .cis.nctu.edu.tw: 140.113.23.3>


第 7 條留言
寄件者:匪諜藏鏡人 (AlbertB.bbs@cis.nctu.edu.tw)
主旨:Re: 結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/19

==> 在 elite@cis_nctu (elite) 的文章中提到:
> ==> 在 AlbertB.bbs@BirdNest.AceArt.Net (雜毛老道藏鏡 的文章中提到:
> > 鐵錯是未必啦,如果你都乖乖的用指標,不要自己用byte-level
> > 存取,應該是不會出錯的.
>   結果真的是錯了,因為我的source資料是外來的,並非結構自己產生的!

外來的? 檔案? 確定11 bits

那好,讀進來的時候先用一個char[11]來存,
再一個個拆到結構裡.

> > Pentium上面資料是一定要alignment的,所以name那邊大概
> > 留了12byte,剛好湊滿32 bit邊界.
> > 可能性不大,這是machine dependence的問題.
>   是machine dependence 還是compiler dependence?
>   因這資料我猜是VB寫出來的,所以懷疑!

我剛剛查了一下,Pentium本身是可以容許某些資料unalignment,
不過這樣效率很差,memory access要很多次.
--
< 壞份子一號簽名檔> Albert B. Wang , Email:albertb@neto.net
< 廣告> 台灣經濟奇蹟幕後的無名英雄! 啊...copy啦! copy啦1....
< 抵制行動> 抗議Hinet放任使用者濫發垃圾電子郵件,請共同抵制 
<faq> 問:為什麼我超頻超不上去? 答:因為你祖宗沒積德,風水不好! </faq>

--
 * Origin: ★ 交通大學資訊科學系 BBS ★ </bbs><bbs .cis.nctu.edu.tw: 140.113.23.3>


第 8 條留言
寄件者:嵐雲 (EightCloud.bbs@csie.nctu.edu.tw)
主旨:Re: 結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/20

==> 在 AlbertB.bbs@cis.nctu.edu.tw (匪諜藏鏡人) 的文章中提到:
: ==> 在 elite@cis_nctu (elite) 的文章中提到:
: >   結果真的是錯了,因為我的source資料是外來的,並非結構自己產生的!
: 外來的? 檔案? 確定11 bits
: 那好,讀進來的時候先用一個char[11]來存,
: 再一個個拆到結構裡.
: >   是machine dependence 還是compiler dependence?
: >   因這資料我猜是VB寫出來的,所以懷疑!
: 我剛剛查了一下,Pentium本身是可以容許某些資料unalignment,
: 不過這樣效率很差,memory access要很多次.
x86 都是允許不 alignment 的 存許的吧!
        unalignment 效率差, 我記得也不是從 pentium 才如此的,
        而是從 486, 還是 386 就有了,
        一些測速程式, 在測 memory 速度, 都有針對不是 alignment
        的存取做測試...

VC++ 的 compiler 都有要不要對 alignment 的設定, 
        絕對不是 machine dependence :)
        (SPARC 的話, 就一定要 alignment 了...)

我在寫程式時, 常常會用這樣的特性, (第一次在 sparc 寫找 bug 找好久...)
        例如, 從某一個位址讀取一個整數...
        我常常會這樣用....
        int   i=*(int*)addr;

        而若在 sparc 上, addr 若不是 4 的倍數, 就 死了..
        只好用 memcpy(&i,addr,sizeof(int));
                or i=(*addr< <24)|(*(addr+1)<<16)... (big endian)
        雖然  在不 alignment 時, *(int*)addr 的讀取效率差,
                還是比 memcpy 或 ... 快得多吧!

        所以在 x86 上
        只是效率不好而以...
        我通常是都把 alignment 關掉, struct 自己填 dummy data
        做最佳化 :)


第 9 條留言
寄件者:23.2℃的陽光 (Omar.bbs@cis.nctu.edu.tw)
主旨:Re: 結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/20

==> 在 elite@cis_nctu (elite) 的文章中提到:
> 若照我的原意,結構長度應該為31 bytes
> struct stocknp
> {
>   char name[11];        11 bytes
>   int vol;               4
>   float open;            4
>   float high;            4
>   float low;             4
>   float close;           4
> };
> 但是以sizeof(stocknp)後卻是32 bytes
> 我的資料恰是上面的結構且是31 bytes
> 但若以read讀資料進來,那存取到的
> vol、open、high鐵錯!
> gcc 有無辦法去取消這種alignment?

  struct stocknp {
    .....
  } __attribute__ ((packed));

  你要的可是這個?

--
Sorcerers have their magic wands;           Lin, Chu-Hui
Witches have their familiars;               Software Engineer
Mystics have their golems;                  R&D Team 4
                                            ASUSTek Computer Inc.
We have our personal computers.             E-Mail: andy_lin@asus.com.tw
--
 * Origin: ★ 交通大學資訊科學系 BBS ★ </bbs><bbs .cis.nctu.edu.tw: 140.113.23.3>


第 10 條留言
寄件者:elite (elite.bbs@cis.nctu.edu.tw)
主旨:Re: 結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/20

==> 在 Omar@cis_nctu (23.2℃的陽光) 的文章中提到:
> > 但是以sizeof(stocknp)後卻是32 bytes
> > 我的資料恰是上面的結構且是31 bytes
> > 但若以read讀資料進來,那存取到的
> > vol、open、high鐵錯!
> > gcc 有無辦法去取消這種alignment?
>   struct stocknp {
>     .....
>   } __attribute__ ((packed));
>   你要的可是這個?
Yes! 帥啊! 請問那裡看到的啊?
K&R 2nd 及C-FAQ都沒有!
--
 * Origin: ★ 交通大學資訊科學系 BBS ★ </bbs><bbs .cis.nctu.edu.tw: 140.113.23.3>


第 11 條留言
寄件者:Steve Lee (chlee@ck.tp.edu.tw)
主旨:Re: 結構的長度
網上論壇:tw.bbs.comp.language
日期:1998/02/21

elite <elite .bbs@cis.nctu.edu.tw> wrote:
: ==> 在 Omar@cis_nctu (23.2℃的陽光) 的文章中提到:
:> > 但是以sizeof(stocknp)後卻是32 bytes
:> > 我的資料恰是上面的結構且是31 bytes
:> > 但若以read讀資料進來,那存取到的
:> > vol、open、high鐵錯!
:> > gcc 有無辦法去取消這種alignment?
:>   struct stocknp {
:>     .....
:>   } __attribute__ ((packed));
:>   你要的可是這個?
: Yes! 帥啊! 請問那裡看到的啊?
: K&R 2nd 及C-FAQ都沒有!

你可以參考 gcc 的 info 。

C Extensions -> Type Attributes
C Extensions -> Alignment

另外, Invoking GCC -> Code Gen Options 裡面有
提到 -fpack-struct ,也可以參考一下。

-- 
Steve, Chia-Huan Lee/李嘉桓
(建中49屆,台大電機101級)
chlee@ck.tp.edu.tw
Advertisements

1 則回應給 stucture word alignment

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

%d 位部落客按了讚: