1、定义结构与初始化
struct A
{
int d1;
int d2[3];
};
A a={1,{1,1,1}};
2、补充内容:内存对齐
struct A
{
char c1;
int d1;
char c2;
};
struct B
{
char c1;
int d1;
char c2;
double d2;
};
一般情况下,int 长度是4字节,要求起始地址与4对齐。那么该结构体中对对齐要求最严格的数据结构就是int,所以会强制让该结构的起始地址满足4的倍数要求。
在内存中会先存储c1,然后空3个字节(满足了d1地址被4整除要求),然后存d1,再存c2。然后再保留3个字节的空白位置。这样内存开销为12(1+3+4+1+3)
对于B,对齐要求为double(8),因此开销为24(1+3空+4+1+7空+8)
我们可以通过调整struct中变量的顺序来节约内存空间。A调整为
struct A
{
int d1;
char c1;
char c2;
};
这样内存开销为8(4+1+1+2)。
3、补充内容:联合和结构在函数传参的时会被完全拷贝一份,传入的是副本
4、补充内容:struct可以用于实现位段——按位分配内存
struct A
{
unsigned int d1:1;
unsigned int d2:1;
unsigned int d3:19;
};
int main()
{
A a;
a.d1 = 0;
a.d2 = 1;
a.d3 = 122;
}
其中d1,d2,d3就被称之为位段。各占据1,1,19个位。
位段的数据类型最常见的是unsigned int,int, unsigned char三种。
补充
不管字节序还是比特序,大端模式是低地址存放高位数据,高地址存放低位数据。
大端模式的字节序:0x123456 ,内存地址从低到高存储的是56,34,12
大端模式的比特序:0x8 ,内存位从低到高存储的是0001 0000
网络序的字节,统一采用大端模式。
5、联合——同一内存空间存不同类型数据
union A
{
int d1;
float d2;
};//4个字节的空间,即存储了d1又存储了d2.成员的类型决定了位是如何被解释的。
union A a;
a.d2 = 3.1415;
printf("%d",a.d1);
联合的sizeof 由联合中的最大元素决定,
union A
{
int d1;
double d2;
};
union A a;
a.d2 = 3.1415;
printf("%d",sizeof(a));//输出是8.
6、补充内容——sizeof()的参数可以是变量也可以是类型
特殊使用场景———零长度数组
struct Msg
{
int l;
int s;
int v[0];
}
这个结构体实例化以后,sizeof()的结果是8,因为数组长度为0,不会占用任何内存。但是在使用的时候可以灵活的调整数组的长度。例如
struct Msg* msg = malloc(sizeof(struct Msg)+sizeof(int)*6);
for(int i=0;i<6;i++)msg->v[i]=i;//这里就是非常灵活的使用
当然实际上引入了VLA以后可以等价为
struct Msg
{
int l;
int s;
int k;
int v[k];
}