2012年6月17日 星期日

[ C/C++ 文章收集 ] Data structure alignment

來源自 這裡 
前言 : 
在Linux下寫ㄧ個 test.c 的程式並定義ㄧ個 t 的struct裡面各有char,short,long,int四種資料型態, 然後把struct的size print出來 : 
 

然後用 gcc 去 compile 並執行 : 
 

但用sizeof所計算出來的t struct卻是 12! (我使用 32bits) 那麼多出來的 1 個byte 是誰佔去了?? 

原因說明 : 
所以程式下面把這個struct的記憶體位置print出來, 轉成方便了解ㄧ點的圖 : 
 

看到沒 char佔 1 byte沒錯, 但是他與下一個short所離的位址卻是2 byte. 這次把 struct 做些修改變成 : 
  1. typedef struct _test  
  2. {  
  3.     char ch0;  
  4.     char ch1;  
  5.     int in;  
  6.     short sh;  
  7. }test;  
結果又更不一樣了 : 
 

整個被偷吃了4 byte! gcc到底搞了什麼鬼呢? WiKi是有解答的 : http://en.wikipedia.org/wiki/Data_structure_alignment 

看到最後面的Example 就是gcc做了padding 的動作 struct變成了 : 
  1. typedef struct _test  
  2. {  
  3.     char ch0;  
  4.     char ch1;  
  5.     char padding0[2];  
  6.     int in;  
  7.     short sh;  
  8.     char padding1[2];  
  9. }test;  
padding 的部份就是我們看起來被吃掉的記憶體 : 
 

解法說明 : 
所以要避免這些 padding 的部份, 一是可以如下自己加入 padding : 
  1. typedef struct _test  
  2. {  
  3.     char ch0;  
  4.     char ch1;  
  5.     short sh;  
  6.     int in;  
  7. }test;  
這樣去執行 : 
 

就不會有被偷吃的地方了, 但是這樣是最基本的人工硬幹方式自己把padding處理掉. 

wiki 會紅不是沒有道理的 後面還有教學, 用 #pragma 來更改packing struct的size成1. 在struct的前後加上 : 
  1. #pragma pack(push) /* push current alignment to stack */  
  2. #pragma pack(1/* set alignment to 1 byte boundary */  
  3. typedef struct _test  
  4. {  
  5.     char ch1;  
  6.     char ch2;  
  7.     int in;  
  8. }test;  
  9. #pragma pack(pop) /* restore original alignment from stack */  
在 64bits 上如果沒有加上 pragma 執行結果會是 : 
 

如果有加上 #pragma 結果會是 : 
 

padding的部份就不見了, 記憶體位址也堆疊起來了. 

補充說明 : 
[C++ 小學堂] pragma comment 的使用

沒有留言:

張貼留言

[Git 常見問題] error: The following untracked working tree files would be overwritten by merge

  Source From  Here 方案1: // x -----删除忽略文件已经对 git 来说不识别的文件 // d -----删除未被添加到 git 的路径中的文件 // f -----强制运行 #   git clean -d -fx 方案2: 今天在服务器上  gi...