结构体进阶
1.结构体内存
1.第一个成员在结构体变量偏移量为零的地址处
2.其他成员变量对齐到某个数字(对齐数)的整数倍的地址处
对齐数=编译器默认的一个对齐数与成员大小的较小值
vs中默认的对齐数是8
3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍
#include<stdio.h>
struct A
{
char a;
short b;
int c;
};
struct B
{
int c;
short b;
char a;
};
struct C
{
char a;
int c;
short b;
};
struct D
{
char a;
char d;
short b;
int c;
};
struct E
{
char a;
short b;
char d;
int c;
};
struct F
{
char a;
short b;
int c;
char d;
short f;
char e;
};
int main(void)
{
printf("A = %d\n", sizeof(aa));//结果:A = 8
printf("B = %d\n", sizeof(bb));//结果:B = 8
printf("C = %d\n", sizeof(cc));//结果:C = 12
printf("D = %d\n", sizeof(dd));//结果:D = 8
printf("E = %d\n", sizeof(ee));//结果:E = 12
printf("F = %d\n", sizeof(ff));//结果:F = 16
return 0;
}
#pragma pack(4) --设置默认对齐数为4
#pragma pack()--取消设置的默认对齐数
偏移量的计算
宏--size_t offsetof(结构体类型名,成员名)
2.位域
1.在结构体定义时,我们可以指定某个成员变量所占用的二进制位数(Bit),这就是位域。
#pragma
pack(2)
typedef
struct
{
char t1 : 8;
int t2 : 1;
int t3 : 30;
}
p;
int main()
{
p s;
printf(
"%d",
sizeof(s));
}
2.C语言标准规定,位域的宽度不能超过它所依附的数据类型的长度。通俗地讲,成员变量都是有类型的,这个类型限制了成员变量的最大长度,
:
后面的数字不能超过这个长度。
3.位域的具体存储规则如下:
1) 当相邻成员的类型相同时,如果它们的位宽之和小于类型的 sizeof 大小,那么后面的成员紧邻前一个成员存储,直到不能容纳为止;如果它们的位宽之和大于类型的 sizeof 大小,那么后面的成员将从新的存储单元开始存储。
#pragma
pack(2)
int main() {
struct
bs {
unsigned m : 12;
unsigned
char ch : 4;
unsigned p : 4;
};
printf(
"%d\n",
sizeof(
struct
bs));
return 0;
}
10
#pragma
pack(4)
int main() {
struct
bs {
unsigned m : 12;
unsigned
char ch : 4;
unsigned p : 4;
};
printf(
"%d\n",
sizeof(
struct
bs));
return 0;
}
12
3) 如果成员之间穿插着非位域成员,那么不会进行压缩。
-
struct bs {
-
unsigned m : 12 ;
-
unsigned ch ;
-
unsigned p : 4 ;
-
} ;
-
12
无名位域一般用来作填充或者调整成员位置。因为没有名称,无名位域不能使用。
-
struct bs {
-
int m : 12 ;
-
int : 20 ; //该位域成员不能使用
-
int n : 4 ;
-
} ;
0宽度位域表示当前整数包已满,下个位域分配 在新整数单元。
#pragma
pack(4)
int main() {
struct
bs {
char a : 4, : 0;
char b : 3;
char c : 1;
};
printf(
"%d\n",
sizeof(
struct
bs));
return 0;
}
2
柔性数组
优点:
方便内存释放;
提高内存利用率(减少内存碎片)
访问效率更高
特点:
1.结构体的柔性数组成员前面必须至少一个其他成员。
2.sizeof返回的这种结构体大小不包括柔性数组的内存。
3.包含柔性数组成员的结构体malloc()函数进行内存的动态分配,并且分配的内存应该大于结构体的大小,以适应柔性数组的预期大小