這酷兄逛C_and_Cpp板轉來的問題..
花了點時間玩了一下
這之前好像有印象會有這種情形 但是沒真的去試過..

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



然後用gcc去compile



但用sizeof所計算出來的t struct卻是12 =\= (1+2+4+4)
那麼多出來的1個byte 是誰佔去了??

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



看到沒 char佔 1 byte沒錯
但是他與下一個short所離的位址卻是2 byte


再來我把同樣的function 放到ARM的CPU上跑
當然也是Linux 只是用arm-linux-gcc做compile


看來跟在PC上執行是同樣的結果

只是在這ARM-Linux上跑 struct的記憶體用的位址都是固定的
在PC上跑記憶體位址會變動


再來把他放到8051上跑 用Keil C 來compile (這我天天在玩的機器阿 @@)



char佔 1 byte
short佔 2 byte
long佔 4 byte
int佔 2 byte
整個struct佔9 byte

int的define跟gcc不一樣 不過看起來Keil C沒有偷佔用記憶體

但是我下面print記憶體位址的寫的有問題
抓不到確切的記憶體位址

所以其實也是有可能是錯誤的
算式或許正確 但是記憶體裡配置的方式可能又另外一回事
這... 下次研究研究


繼續把平台轉回到PC上
但是這次把struct做些修改
變成
typedef struct _test
{
char ch0;
char ch1;
int in;
short sh;
}test;

結果又更不一樣了

整個被偷吃了4 byte

gcc到底搞了什麼鬼呢?

WiKi是有解答的
http://en.wikipedia.org/wiki/Data_structure_alignment

看到最後面的Example
就是gcc做了padding的動作
struct變成了

typedef struct _test
{
char ch0;
char ch1;
char padding0[2];
int in;
short sh;
char padding1[2];
}test;

padding的部份就是我們看起來被吃掉的記憶體



所以要避免這些padding的部份
對我來說最爛方式就是自己算好
例如改成
typedef struct _test
{
char ch0;
char ch1;
short sh;
int in;
}test;
這樣去執行



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

wiki會紅不是沒有道理的 後面還有教學
用#pragma來更改packing struct的size成1

在struct的前後加上
#pragma pack(push) /* push current alignment to stack */
#pragma pack(1) /* set alignment to 1 byte boundary */
typedef struct _test
{
char ch0;
char ch1;
int in;
short sh;
}test;
#pragma pack(pop) /* restore original alignment from stack */

再執行



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

看wiki長智慧..
下次注意注意..

arrow
arrow
    全站熱搜

    changeway 發表在 痞客邦 留言(3) 人氣()