在這裏只總結結構體的字節對齊問題,看下面的結構體
struct s1
{
char a;
int b;
short c;
};
struct s2
{
char a;
short c;
int b;
};
那麼sizeof(s1) = 12, sizeof(s1) = 8;
我們可以假定結構體在內存中的地址是0x0000開始的,那麼我們說的字節對齊就是(起始內存地址%自身類型字節) = 0;
所以在這裏簡單分析下s1是怎麼對齊的
a的內存地址是0x0000,自身字節1,它是自然對齊的,
b的自身類型字節是4,如果要對齊,那麼起始地址只能是0x0004,範圍到0x0007.
c的自身類型字節是2,故起始地址爲0x0008,範圍到0x0009故不用填充了直接跟在b變量後面,
爲什麼還要補全兩個字節呢,因爲假定這是一個結構體數組,那麼,下個元素的起始地址是不是也要對齊,所以不管後面有沒有變量,都要內存對齊,纔不會對後面的變量產生字節不對齊的影響,並且結構體最後補全的字節數取決於變量的最大類型的整數倍,即,在上面是int佔四字節,所以結構體的內存必然是4的倍數
當結構體中有char a[0]成員,這樣的成員時,這是不會增加結構體內存的,但是a的地址是上面那個成員的地址加一,也就是a後面的成員的地址
補充:對於改變指定字節的方法有幾種
一.
#pragma pack (n) //n就是指定的字節
struct ss{
.......
};
#pragma pack () //取消指定字節
二.
struct ss
{
.....
}__attribute__ ((packed)); //指定最小字節對齊,一個字節
三.
struct stu{
....
}__attribute__ ((aligned (1))); //數字爲指定一個字節
在這裏說一下,這是筆者自己的理解,對於不同平臺有不同的規定,像X86平臺,字節不對齊只是影響cpu讀取內存的速度,但是有些平臺必須嚴格對齊,不然會發送錯誤。這麼說那麼就是說cpu也不是按程序員想象那樣,int型的就一次去取int型所佔有的字節數,而是按照變量存儲在內存中什麼位置來決定取的次數,接着纔是取多少個字節,有不同看法的請指教
補充:如果能分析下面的結構體內存,你就真懂了字節對齊
struct aa
{
char a;
int b;
double c;
};
struct bb
{
char d;
struct
{
int e;
double f;
};
int g;
};
結果是sizeof(aa) = 16; sizeof(bb) = 32
提示:其實結構體套結構體也是一樣的都是按最大字節對齊(按結構體中最大的類型對齊,不是類型的疊加),比如上面的struct bb;自己思考吧
下一篇是關於位域在struct中佔的內存