#include <stdio.h>
struct TYPEA
{ short int code;
float value;
char flags;
};
struct TYPEB // TYPEA 與 TYPEB 只有成員順序不同
{ float value;
short int code;
char flags;
};
void main(void)
{
printf("sizeof(TYPEA) = %d\n", sizeof(TYPEA));
printf("sizeof(TYPEB) = %d\n", sizeof(TYPEB));
}
上例的執行結果是:
sizeof(TYPEA) = 12
sizeof(TYPRB) = 8
sizeof(TYPRB) = 8
為甚麼會不一樣?好像都是 4 的倍數?其實這是因為編譯器對 struct 作了最佳化,以現行 32-bits 的 CPU (或 32-bits 的應用程式)而言,CPU 的行為一次抓取就是 4 bytes,以下圖最左邊的狀況,假如編譯器未對 TYPEA 做最佳化,那麼它的 value 欄位剛好跨在 CPU 兩次抓取範圍之間,所以程式碼中要取用 value 欄位的時候,CPU 必須抓取兩次,然後取第一次抓取的後半部和第二次抓取的前半部才能或得 value 的資料內容,相當傷害效率,所以通常編譯器在安排 TYPEA 的記憶體布局(layout)的時候,會採用下圖中的設計,盡量保證 struct 自訂型別中的任何欄位 都可以一次抓取(除非像 double 或 64-bit 整數本身就已經 8 bytes 長),方法就是盡量讓資料欄位的位址落在 4 bytes 的記憶體邊界(boundary)上,甚至把整個結構體的尺寸填空到 4 的倍數,令後續的資料也會落在 4 bytes 倍數的位址上。
當然上圖中的 TYPEA 造成了記憶體的浪費,所以,好的 struct 設計應該主動地把資料欄位都放置 4 的倍數上,如 TYPEB 型別,雖然欄位和 TYPEA 相同,但是變個順序,就兼顧了效率和記憶體空間的要求了。除此之外,請記得struct 的尺寸不一定等於成員的尺寸和,所以計算配置記憶體所需的記憶體空間請務必使用 sizeof( )。
沒有留言:
張貼留言