结构体的对齐规则:
1. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8(linux对齐数就是元素自身大小,除非手动修改).
3. 结构体总大小为所有成员对齐数中最大的那个(每个成员变量都有一个对齐数,第二条比较后小的才叫成员的对齐数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体(即内层的结构体)对齐到自己的最大对齐数的整数倍处(即内层结构体对外层对齐数也有一个对齐数,为内层结构体自己内部成员对齐数中最大的那个和编译器默认对齐数比,较小的为内层结构体对外层的对齐数),结构体的整体大小就是 所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
所以如上图第一例所示的内存空间则为:
更新:
#include <iostream>
using namespace std;
//t为结构体类型不占大小
struct test {
short a;//2+2(e对齐数4所以补2)
struct t {
int b;
double c;
char d;
};
int e;//4
}test;
//t1为test1的内部成员占大小,先算内部的
struct test1 {
short a;//2+6(t1最大对齐数8和默认对齐数8比较小的时8所以补到8,得加6)
struct t1 {
int b;//4 + 4(补的4因为double和默认对齐数都是8,所以对齐到8的整数倍加4)
double c;//8(后面时1,咋样都是整数倍不用补)
char d;//1+7(最大成员对齐数8的整数倍所以补7)
}t1;
int e;//4+4(前面已经2+6+24=32已经是4的整数倍所以t1后不用补,a对齐数2,t1对齐数8,e对齐数4,32+4=36得补到最大成员对齐数整数倍所以加4)
}test1;
//t2为test2的内部成员占大小,先算内部的,算法和test1同理
struct test2 {
short a;
struct {
int b;
double c;
char d;
};
int e;
}test2;
int main()
{
cout << sizeof(test) << endl;//8
cout << sizeof(test1) << endl;//40
cout << sizeof(test2) << endl;//40
}
例二:
例二内存为:
例三:
例三内存为:
位段:
位段元素只能是int,unsigned int类型,位段可以用来应用于ip报文之类的:
冒号后的数字表示占多少个比特位(二进制位),不足8也算一个字节大小,例如:
枚举:
枚举理论上来说也是自定义类型,但在c语言中被完全当成int常量....
像这样的代码是可行的:
week和sex并没有关系,但在c枚举中可以相互赋值或者进行加减操作.
enum week{
monday,
tuesday,
wednesday
};
enum sex{
man,
wuman
};
int main(){
enum sex s=man;
s=monday;
}
枚举第一个元素没有赋初值就是0,后面的元素递增加1,若中间元素有赋值则从中间这个元素的值开始递增加1.
联合体:
联合体里面的元素共同同一段内存.
联合体也有类似结构体的内存对齐规则.
联合体可以应用于表示ip地址,判断大小端等.
例如: