目录
1.结构体内存大小
2.修改默认对齐数
3.函数传参
4.位段
5.枚举
6.联合体
1.结构体内存大小
在结构体设计时,我们既要满足对齐,又要节省空间,如何做到:这就需要我们让占用空间小的成员尽量集中在一起。例如:
上面是当我们设计为struct s1时,占用空间情况。显然,我们用struct s1更节省空间。
2.修改默认对齐数
当对齐数为1时,s1的最后大小为6
3.函数传参
先看如下两段代码:
#includestruct S { int data[1000]; int num; }; void print1(struct S tmp) { int i = 0; for (i = 0; i < 10; i++) { printf("%d ", tmp.data[i]); } printf("nnum=%dn", tmp.num); } int main() { struct S s = { {1,2,3,4,5,6,7,8,9,10},100 }; print1(s); return 0; }
#includestruct S { int data[1000]; int num; }; void print2(const struct S *ps) { int i = 0; for (i = 0; i < 10; i++) { printf("%d ", ps->data[i]); } printf("nnum=%dn", ps->num); } int main() { struct S s = { {1,2,3,4,5,6,7,8,9,10},100 }; print2(&s); return 0; }
通过比较上面的print1和print2函数,我们可以发现print2函数更好。因为函数传参的时候,参数需要压栈,会有时间和空间的系统开销。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。
4.位段
位段的声明和结构体是类似的,有两个不同:
1.位段的成员必须是int,unsigned int或signed int
2.位段的成员名后边有一个冒号和数字。
位段是可以节省空间的,但是有跨平台问题存在。
struct A
{
int _a : 2;
int _b : 5;
int _c : 10;
int _d : 30;
};
int main()
{
printf("%dn", sizeof(struct A));
return 0;
}
5.枚举
优点:
1)增加代码的可读性和可维护性;
2)和#define定义的标识符比较枚举有类型检查,更加严谨;
3)防止了命名污染(封装);
4)便于调试;
5)使用方便,一次可以定义多个常量。
#includeenum color { RED, GREEN, BLUE }; int main() { //printf("%dn", RED); //printf("%dn", GREEN); //printf("%dn", BLUE); enum color c = GREEN; if (c == GREEN) { printf("绿色n"); } return 0; }
6.联合体
联合也是一种自定义类型
union Un
{
char c;
int i;
};
int main()
{
union Un u={0};
printf("%pn", &u);
printf("%pn", &(u.c));
printf("%pn", &(u.i));
return 0;
}
i和c共同占用同一个字节
联合大小的计算:
联合的大小至少是最大成员的大小
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
例如:
union Un1
{
char c[5];// 5 1
int i;//4 4
};
union Un2
{
short c[7];//14 2
int i;//4 4
};
int main()
{
printf("%dn", sizeof(union Un1));//8
printf("%dn", sizeof(union Un2));//16
return 0;
}


