结构体对齐详解
1、一般設置的對齊方式為1,2,4字節對齊方式。結構的首地址必須是結構內最寬類型的整數倍地址;另外,結構體的每一個成員起始地址必須是自身類型大小的整數倍(需要特別注意的是windows下是這樣的,但在linux的gcc編譯器下最高為4字節對齊),否則在前一類型后補0;這里特別提到的是數組一定要注意,而且在一些編程的技巧中,我們可以使用數組強制字節達到對齊的目的。這在網絡編程中是很常見的。
舉例:比如CHAR型占用空間為1字節,則其起始位置必須可被1整除。INT為4字節,其起始位置必須被4帶隊,依次類推。(我們假定類或結構體的起始位置為0位置,其實編譯器是在開辟空間時,會尋找起始位置可被結構內最寬類型整除的地址做為開始地址,因此我們可以假定其為0值,因為這0值可以被任意的類型整除。)
2、結構體的整體大小必須可被對齊值整除,默認4(結構中的類型大小都小于默認的4)。
3、結構體的整體大小必須可被本結構內的最寬類型整除。(其實和上一條是一樣的,但這里獨立出來,起注意作用。比如結構體里的有DOUBLE,那么結構的大小最后必須可被8整除)
注意:GCC不是這樣,就是最高只能被4整除。此為32位系統,64為系統也會采用8整除的方式。否則(2、3條),編譯器會在結構的最后添充一定的特定字符來補齊。
struct T?
{?
char ch;?
double d ;?
};
此結果強調為32系統在VC中是16個字節,GCC中為12個字節。64位依舊是16個字節
4、對于結構體內嵌套結構體的形勢,規定是必須按照基本數據類型來定義,而不能以嵌套結構大小來做為上三種使用的基準。(總結)結構體可以處理成char類型。
二、舉例:
struct A?
{?
? ? int a; ? ?
? ? char b;?
? ? short c;?
}; ?//8
struct B?
{?
? ? char b;?
? ? int a;?
? ? short c;?
}; ?// 12
struct C?
{?
? ? double t;?
? ? char b;?
? ? int a;?
? ? short c;?
}; //24
struct D?
{?
? ? char b;?
? ? double t;?
? ? int a;?
? ? short c;?
};//24
在VC中,SIZEOF這四個結構體,分別為:8、12、24、24;
我們先談第一個,(說明一下,在考慮結構體大小時,我們基本可以忽略起始地址的問題,因為這個編
譯器會自動為我們做好,見上面的說明),結構體內首先是一個INT的4字節,起始地址假定為0,整除4,其小于等于默認的4字節對齊且0為4(INT的占用空間)的整數倍,所以,其占四個字節;其后為起始地址為5,空間為1個字節的CHAR,小于4且5為1(CHAR占用空間)的整數倍,故占用1個字節,然后是一個起始地址為5占2個字節的SHORT,其小于4,但5不為2位數,故補齊一個字節,從第6個字節開始,占2字節空間。所以共占用4+1+1(補)+2=8;8/4=2;整除,故占用8字節空間。
再談第2個,CHAR不用解釋,占有一個字節空間,且可以被0地址整除。而INT則占4字節空間,所以其必須在CHAR后補齊3字節,到第四個字節,才是INT的真正地址。SHORT也不用說,所以共占有:1+3(補)+4+2=10個字節,但10不能整除4,所以要在結構體最后補齊2字節。故實際占有10+2= 12個字節。
談第三個,C結構體只是在B結構體前加了一個DOUBLE,其它都一樣,按說應該是20個字節啊,但注意我們上面規則的第3條。必須是最寬類型的整數倍,一定要分清,所以得補齊到24,D結構體類似,不再講。
| GCC 32位 sizeof(char) = 1 sizeof(double) = 8 sizeof(float) = 4 sizeof(int) = 4 sizeof(short) = 2 sizeof(long) = 4 sizeof(long long) = 8 sizeof(long double) = 12 sizeof(complex long double) = 24 指針是4字節; | GCC 64位 sizeof(char) = 1 sizeof(double) = 8 sizeof(float) = 4 sizeof(int) = 4 sizeof(short) = 2 sizeof(long) = 8 sizeof(long long) = 8 sizeof(long double) = 16 sizeof(complex long double) = 32 指針是8字節 |
__attribute__ 的語法為:
__attribute__ ((語法列表))參數aligned(number) [number為最小對齊的字節數]是用得較多的一個。
另一個是參數packed 表示“使用最小對齊”方式,即對變量是字節對齊,對于域是位對齊。
#include <stdio.h> struct A{ char a; ? ? ? ? ?//1Byte int b; ? ? ? ? ? //4B unsigned short c;//2B long d; ? ? ? ? ?//4B unsigned long long e; //8B char f; ? ? ? ? ? ? ? //1B };
struct B{ char a; int b; unsigned short c; long d; unsigned long long e; char f; }__attribute__((aligned));
struct C{ char a; int b; unsigned short c; long d; unsigned long long e; char f; }__attribute__((aligned(1)));
struct D{ char a; int b; unsigned short c; long d; unsigned long long e; char f; }__attribute__((aligned(4)));
struct E{ char a; int b; unsigned short c; long d; unsigned long long e; char f; }__attribute__((aligned(8)));
struct F{ char a; int b; unsigned short c; long d; unsigned long long e; char f; }__attribute__((packed));
struct H{ char a; double b; }; int main(int argc, char **argv) { struct A a; struct B b; struct C c; struct D d; struct E e; struct F f;
printf("A = %d, B = %d, C = %d, D = %d, E = %d, F = %d, H = %d\n", sizeof(struct A), sizeof(struct B), sizeof(struct C), sizeof(struct D), sizeof(struct E), ? ? ? sizeof(struct F),sizeof(struct H)); return 0; }
結果: $ ./aligned32?
A = 28, B = 32, C = 28, D = 28, E = 32, F = 20, H = 12?
$ ./aligned64?
A = 40, B = 48, C = 40, D = 40, E = 40, F = 24, H = 16
總結
- 上一篇: 需求调研(二)
- 下一篇: new php,PHP: 新特性 - M