- 前言
一、结构体类型
二、位段
三、枚举类型
四、联合体类型
- 总结
前言
在现实中,我们有很多的东西不能单纯用整型或者浮点型来表示,所以这里就需要自定义类型来补充这部分内容。
这篇文章能帮助你更好的了解C语言的自定义类型。
一、结构体类型
结构体是C语言中非常重要的一个自定义类型,很多时候都需要用到它。
- 什么是结构体
它的关键字是 struct,下面我就声明一个结构体
struct Person
{
char name[12];
int age;
char sex[5];
}
这就是一个人的结构体,它有姓名、年龄、性别等三个成员。
同时,结构体还可以嵌套,就是一个结构体里面可以包含其他结构体类型的成员。
- 结构体的内存对齐
那么结构体的大小该如何计算呢?
首先我们需要掌握结构体的内存对齐规则。
- 第一个成员在与结构体变量便宜量为0的地址处
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
(对齐数=编译器默认的对齐数和该成员大小的较小值)
- 结构体总大小为最大对齐数的整数倍
struct s
{
char n;
int k;
double m;
}
这个结构体的大小就为: 1 + 3(内存对齐浪费的空间)+ 4 +8 = 16
- 为什么要有内存对齐呢?
- 不是所有的平台都能访问任意地址上的任意数据的,某些平台只能在某些地址处取某些特定类型的数据。
- 数据结构(尤其是栈)应该尽可能在自然边界上对齐。
在设计结构体时,如果要尽量节省空间,可以让空间小的成员尽量集中在一起。
#pragma pack() 可以修改结构体的对齐数
- 结构体传参
struct S
{
int data;
int num;
};
struct S s = {1,100};
//结构体传参
void print1(struct S s)
{
printf("%d",s.num);
}
//结构体地址传参
void print2(struct S* s)
{
printf("%d",s->num);
}
二、位段
- 什么是位段
位段的声明和结构体类似,有两个不同:
1.位段成员必须是int、unsigned int、signed int。
2.位段成员的后面有一个冒号和一个数字。
如:
struct S
{
int a:2;
int b:4;
int c:8;
};
这里的数字就代表成员占了多少个bit位,并且位段的空间是按照需要以4个字节(int)或者1个字节(char)来开辟的。
在vs上面S的大小就为4个字节
三、枚举类型
关键字enum
把所有可能的值列举出来
如:
enum sex
{
man;
woman;
}
enum sex a = man;
enum sex b = woman;
枚举的成员都是有值的,默认从0开,也可以手动赋值。
- 枚举的优势
1.增加了代码的可读性和可维护性
2.和#define定义的标识符相比,枚举有类型检查,更加严谨
3.防止了命名污染
4.使用方便,可以一次定义多个常量
四、联合体类型
关键字union
它也是可以包含一系列的成员,但不同的是他们公用一个空间,从一个起始地址开始。
所以联合体的大小最少也是最大成员的大小。
union un
{
char c;
int i;
}
union un c;
这里un的大小为4;
当最大成员的大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。
下面举一个结构体的使用示例:
判断大小端
union
{
char c;
int i;
}u;
u.i=1;
return u.c;
这里如果 返回的是1则为小端存储,为0则是大端。
总结
自定义类型就讲到这里,希望你能够从中学到知识。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)