结构体定义:
我们先来看一下结构体的定义。什么叫结构体呢?结构是一些值的集合,这些值叫做成员变量,总体称为一个结构体,结构体的每个成员可以使不同类型的变量。结构体类型是一种自定义类型。用户根据需求自己进行的类型。
结构体的声明:
用一个栗子说明一下吧。struct Stu
{
char name[20];
int age;
char sex[5];
double tel;
};
上述声明了一个学生的结构体,struct结构体关键字,Stu叫做结构体名,大括号里是它的成员,其中包括名字,年龄,性别,电话。
当结构体声明好的时候,并没有向内存申请空间,当创建了结构体变量struct Stu s1时,才向内存申请了空间。
特殊声明:(匿名结构体类型)
struct
{
char name[20];
int age;
char sex[5];
double tel;
}s1,s2;
匿名结构体类型变量,在声明这个结构体的时候就要定义s1,s2这些变量。
匿名结构体类型在成员变量一样的时候,但因为匿名,它也会被编译器认为成两种不同的类型。所以这是非法的。
结构体成员:
struct Stu
{
char name[20];
int age;
char sex[5];
};
如何去访问结构体的成员呢?用操作符 .或者->
struct Stu s1;
strcpy(s1.name, "lili");
s1.age = 20;
strcpy(s1.sex, "male");
struct Stu *pstu;
(*pstu).age = 20;
pstu->age = 20;
结构体初始化:
struct Stu s1 = { “lili” , 20 , “nv” };
也可以在声明结构体定义变量的时候进行初始化。
struct Stu
{
char name[20];
int age;
char sex[5];
}s1 = { "lili" , 20 , "nv" };
结构体传参:
结构体传参时,要传结构体的地址。
原因是在传递一个结构体对象时,结构体过大的话,参数要进行压栈,需要的系统开销就比较大,这就会导致性能下降。下面举一个简单的例子:
struct Stu
{
char name[20];
int age;
char sex[5];
}s1 = {"lili",20,"nv"};
void print(struct Stu* ps)
{
printf("%d\n", ps->age);
}
int main()
{
print(&s1);
system("pause");
return 0;
}
位段:
什么是位段呢?位指的是比特位,位段是用结构体实现的。位段的成员类型成员需是 int,unsigned int,char 。位段的成员名后边有一个冒号和一个数字,表示占几个比特位。
struct A
{
int _a : 2;
int _b : 5;
int _c : 10;
int _d : 30;
};
这就是一个位段类型。它的大小是多少呢?
下来来看一下为啥结果是8?
那就得先来看一下位段是怎么进行内存分配了?
- 位段的成员可以是int,unsigned int, char ,char也属于整型家族。
- 位段上一次性开辟4 个字节空间(int,unsigned int)或者1 个字节空间(char)。
位段有什么不确定因素,是不跨平台的,可移植的程序应避免使用位段。
因为是int类型,所以一开始申请四个字节空间大小,_a占2个比特位,_b占5个比特位,加起来就是7个比特位,_c占10个比特位,刚才第一个字节用了7个比特位,还有一个,不够_c存放,所以还需要二个字节空间才能放得下,就会还剩下6个比特位。_d占30个比特位,剩下申请的空间不够存放30个比特位,所以要重新开辟四个字节空间,因为位段开辟int类型一次需要开辟四个字节空间。所以结果输出是8,大小是8个字节。
下来我们看一下位段的空间分配:
int main()
{
char pub[4] = { 0 };
struct S
{
char a : 3;
char b : 4;
char c : 5;
char d : 4;
}*ps;
ps = (struct S*)pub;
ps->a= 10;
ps->b = 12;
ps->c = 3;
ps->d = 4;
printf("%02x,%02x,%02x,%02x", pub[0],pub[1],pub[2],pub[3]);
/*printf("%d\n", sizeof(struct A));*/
system("pause");
return 0;
}
结果:
看一下图解:
位段是不跨平台的,有以下几点注意的:
- int位段是有符号还是无符号是不确定的;
- 位段最大数目不确定;
- 位段成员在内存中从左向右分配,还是从右向左分配尚未定义;
- 当一个结构包含两个位段,第二个位段成员较大,无法容纳第一个位段剩余位时,是舍弃还是利用,也是不确定的。
总结:位段可以很好地节省空间,但是存在跨平台问题。