#include <stdio.h> #pragma pack(8) struct example1 { short a; long b; }; struct example2 { char c; example1 struct1; short e; }; int main(void) { example2 struct2; printf("%u\n", sizeof(example1)); printf("%u\n", sizeof(example2)); printf("%u\n", (unsigned int)(&struct2.struct1) - (unsigned int)(&struct2)); return 0; }
今天須要仔細的總結一下內存對齊機制了,參考了http://www.cnblogs.com/clover-toeic/p/3853132.html的博文。html
首先須要牢記對其準則:linux
①數據類型自身的對齊值,例如char自身對齊值爲1字節,int爲4字節數據結構
②結構體或類的自身對齊值,其成員中自身對齊值最大的那個值函數
③制定對齊值,#pragma pack(value)時制定對齊值spa
④數據成員,結構體和類的有效對齊值,爲其中自身對齊值和指定對齊值中較小者,即有效對齊值。code
其中,有效對齊值N是最終用來決定數據存放地址方式的值。有效對齊N表示「對齊在N上」,即該數據的「存放起始地址%N=0」。而數據結構中的數據變量都是按定義的前後順序存放。第一個數據變量的起始地址就是數據結構的起始地址。結構體的成員變量要對齊存放,結構體自己也要根據自身的有效對齊值圓整(即結構體成員變量佔用總長度爲結構體有效對齊值的整數倍)。htm
字節數規定:blog
①sizeof(short int)<=sizeof(int)內存
②sizeof(int)<=sizeof(long int)get
③short int至少應爲16位(2字節)
④long int至少應爲32位。
由此開始分析這個題目的解答:
從#include看起,包含了stdio.h頭文件。同時用預處理命令使③制定的自身對齊值爲8,
從main函數開始分析,首先聲明瞭一個example2結構體,而後打印example1,example2結構體的佔用字節空間大小,最後打印example2結構體中,example1結構體的地址減去example2結構體地址的值。
main函數很簡單,而後來看example1結構體。結構體包含short和long,因爲32位機器short2字節,long4字節,因此結構體最大自身對齊值爲4,此時內存分配爲short 2,填充 2,long 4,總共佔用8字節。
example2結構體中example1結構體最大對齊值爲4,char爲1,short爲2,預處理定義爲8,因此仍是按照4字節對齊,此時內存分配爲char 1,填充 3,example1 8,short 2,填充 2,總共佔用16字節。
因爲建立的堆棧是在堆上分配的,堆地址是遞增的,假設example2的初始地址爲x,而後char和填充字節佔了4字節,而後就是example1結構體了,so,(unsigned int)(&struct2.struct1) - (unsigned int)(&struct2)爲(x+4)-x = 4。
本次驗證採用了visual studio,本機電腦爲linux,等到週三考完試把visual studio 截圖拷上去
deepin 15.3 64驗證結果以下: