目录
1.结构体内存大小
在结构体设计时,我们既要满足对齐,又要节省空间,如何做到:这就需要我们让占用空间小的成员尽量集中在一起。例如:
上面是当我们设计为struct s1时,占用空间情况。显然,我们用struct s1更节省空间。
2.修改默认对齐数
当对齐数为1时,s1的最后大小为6
3.函数传参
先看如下两段代码:
#include<stdio.h>
struct 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=%d\n", tmp.num);
}
int main()
{
struct S s = { {1,2,3,4,5,6,7,8,9,10},100 };
print1(s);
return 0;
}
#include<stdio.h>
struct 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=%d\n", 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("%d\n", sizeof(struct A));
return 0;
}
5.枚举
优点:
1)增加代码的可读性和可维护性;
2)和#define定义的标识符比较枚举有类型检查,更加严谨;
3)防止了命名污染(封装);
4)便于调试;
5)使用方便,一次可以定义多个常量。
#include<stdio.h>
enum color
{
RED,
GREEN,
BLUE
};
int main()
{
//printf("%d\n", RED);
//printf("%d\n", GREEN);
//printf("%d\n", 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("%p\n", &u);
printf("%p\n", &(u.c));
printf("%p\n", &(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("%d\n", sizeof(union Un1));//8
printf("%d\n", sizeof(union Un2));//16
return 0;
}