VC++中結構體的存儲

朗訊的筆試題是這樣的:

Typedef union student

{

       Char name[10]

       Long sno;

       Char sex;

       Float score [4];

} STU;

Main ()

{

STU a[5]

Printf(“%d/n”,sizeof(a)

}

答案是80 ,因爲union是可變的以其成員中最大的成員作爲 union的大小!

但是換成是 struct又是多少呢?

Typedef struct student

{

       Char name[10]

       Long sno;

       Char sex;

       Float score [4];

} STU;

Main ()

{

STU a[5]

Printf(“%d/n”,sizeof(a)

}

答案是 180  ????爲什麼不是 (10+4+1+16)*5=155? 因爲struct 有個叫對齊方式的問題:

         不對齊的數據存取在x86上影響速度,因爲在不對齊的時候,對於小的可能會影響 其效率,對齊即是多分配一些字節,填充無用數據,以空間的損失來換取消率。

       struct是一種複合數據類型,其構成元素既可以是基本數據類型(如intlongfloat等)的變量,也可以是一些複合數據類型(如arraystructunion等)的數據單元。對於結構體,編譯器會自動進行成員變量的對齊,以提高運算效率。缺省情況下,編譯器爲結構體的每個成員按其自然對齊(natural alignment)條件分配空間。各個成員按照它們被聲明的順序在內存中順序存儲,第一個成員的地址和整個結構的地址相同。

      自然對齊(natural alignment)即默認對齊方式,是指按結構體的成員中(類型)size最大的成員作爲基本的分配單元,而且與其順序有這密切的聯繫。

     例如:

struct naturalalign
{
 char a;
 short b;
 char c;
};

  在上述結構體中,size最大的是short,其長度爲2字節,因而結構體中的char成員ac都以2爲單位對齊,sizeof(naturalalign)的結果等於6

    如果改爲:

struct naturalalign
{
 char a;
 int b;
 char c;
};

  其結果顯然爲12

    那麼再回到到原題:結構體中,size最大的是longsize 4,所以,按照順序,Char name[10]12個字節;Long sno; 4個字節;Char sex; 4個字節(這裏對齊了);Float score [4]; 16個字節。於是(12+4+4+16×5180,就是了!

     剛纔還說過,與順序有關,呵呵,我們改一下:

Typedef struct student

{

       Char name[10]

       Char sex;

       Long sno;

       Float score [4];

} STU;

Main ()

{

STU a[5]

Printf(“%d/n”,sizeof(a)

}

Main ()

{

STU a[5]

Printf(“%d/n”,sizeof(a)

}

 

答案是:160. 爲什麼,只是換了順序而已呀?關鍵就在順序上。

結構體中,size最大的是longsize 4,所以,按照順序,Char name[10]12個字節;但是這12中多分配的2個字節可以包含後面的Char sex; 問題就在這);Float score [4]; 16個字節。於是(12+4+16×5160,就是了!

所以要小心呀!

2.2指定對齊

  一般地,可以通過下面的方法來改變缺省的對齊條件:

  · 使用僞指令#pragma pack (n),編譯器將按照n個字節對齊;
  · 使用僞指令#pragma pack (),取消自定義字節對齊方式。

  注意:如果#pragma pack (n)中指定的n大於結構體中最大成員(類型)的size,則其不起作用,結構體仍然按照size最大的成員進行對齊。

     例如:

#pragma pack (n)
struct naturalalign
{
 char a;
 int b;
 char c;
};
#pragma pack ()

  當n4816時,其對齊方式均一樣,sizeof(naturalalign)的結果都等於12。而當n2時,其發揮了作用,使得sizeof(naturalalign)的結果爲6

  在VC++ 6.0編譯器中,我們可以指定其對齊方式(見圖1),其操作方式爲依次選擇projetct > setting > C/C++菜單,在struct member alignment中指定你要的對界方式。

1VC++ 6.0中指定對界方式

  另外,通過__attribute((aligned (n)))也可以讓所作用的結構體成員對齊在n字節邊界上,但是它較少被使用,因而不作詳細講解。

Typedef struct student

{

       Char name[10]

       Char sex;

       Long sno;

       Float score [4];

} STU;

Main ()

{

STU a[5]

Printf(“%d/n”,sizeof(a)

}

Main ()

{

STU a[5]

Printf(“%d/n”,sizeof(a)

}

 

答案是:160. 爲什麼,只是換了順序而已呀?關鍵就在順序上。

結構體中,size最大的是longsize 4,所以,按照順序,Char name[10]12個字節;但是這12中多分配的2個字節可以包含後面的Char sex; 問題就在這);Float score [4]; 16個字節。於是(12+4+16×5160,就是了!

所以要小心呀!

2.2指定對齊

  一般地,可以通過下面的方法來改變缺省的對齊條件:

  · 使用僞指令#pragma pack (n),編譯器將按照n個字節對齊;
  · 使用僞指令#pragma pack (),取消自定義字節對齊方式。

  注意:如果#pragma pack (n)中指定的n大於結構體中最大成員(類型)的size,則其不起作用,結構體仍然按照size最大的成員進行對齊。

     例如:

#pragma pack (n)
struct naturalalign
{
 char a;
 int b;
 char c;
};
#pragma pack ()

  當n4816時,其對齊方式均一樣,sizeof(naturalalign)的結果都等於12。而當n2時,其發揮了作用,使得sizeof(naturalalign)的結果爲6

  在VC++ 6.0編譯器中,我們可以指定其對齊方式(見圖1),其操作方式爲依次選擇projetct > setting > C/C++菜單,在struct member alignment中指定你要的對界方式。

1VC++ 6.0中指定對界方式

  另外,通過__attribute((aligned (n)))也可以讓所作用的結構體成員對齊在n字節邊界上,但是它較少被使用,因而不作詳細講解。

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章