C语言全网最详细对自定义数据类型的讲解

新星杯·14天创作挑战营·第18期 10w+人浏览 193人参与

前言

读者朋友们你好,今天主要讲解一下自定义数据类型结构体。共用体和枚举。制作不易,如果有帮助希望点个关注。
3步讲明白结构体内存对齐。


一、结构体声明和创建

声明:

struct tag
{
	member - list;//结构体成员可以是任何类型的
}variable - list;//创建变量(可有可无)。
例:
struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
};

1.结构体的特殊声明

匿名结构体:
在写结构体时可以不声明:

struct
{
	int a;
	char b;
};
struct
{
	int a;
	char b;
}x;

像这种,匿名结构体,只能使用一次。虽然跟下面的内容一样,但这是两个不同的结构体,所以使用这种匿名结构体,应该直接在分号(;)前面创建变量。

2.结构体的自引用

struct Node
{
	int data;
	struct Node next;
};//这种是不行的,struct Node内部还包含
//一个struct Node变量,最后结果是正无穷大
struct Node
{
	int data;
	struct Node * next;
};//应该是个指针,因为指针的大小是确定的,

二、结构体内存对齐

1.对齐规则

  1. 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处(也就是第一个成员从0开始
  2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。
  3. 结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。
    对⻬数 = 编译器默认的⼀个对⻬数(VS默认为8) 与 该成员变量⼤⼩的较⼩值

例:

struct aaa
{
	char a[5];//对齐数1<8,所以是1
	int ;//对齐数4<8,所以是4
};

第二个为int类型4和8比,对齐数是4,所以对齐到4的整数倍,所以应该最小从4开始,因为第一个地址是char a占5个字节(从0开始)刚好到4,所以b要从8开始往后数(8、9、10、11)。最大对齐数是4,一共占11个字节,离得最近的4的整数倍是12,所以一共占12个字节
接下来讲一下结构体嵌套的讲解

struct aaa
{
	char a[5];//对齐数1<8,所以是1
	int ;//对齐数4<8,所以是4
};
struct bbb
{
	char a;//对齐数1<8,所以是1
	struct aaa s1;//对齐数为内部成员的最大对齐数(4)
};

因为第二个成员最大对齐数是4,所以是从4开始一共12个字节,总大小为16个字节

2.为什么有内存对齐

总体来说:内存对齐其实是用空间来换时间
尽量让小的成员在一起可以省略

3.修改默认对齐数

#pragma这个预处理指令,可以改变编译器的默认对齐数

#pragma pack(1)//设置默认对⻬数为1
struct S
{
char c1;
int i;
char c2;
};
#pragma pack()//取消设置的对⻬数,还原为默认

4.结构体传参

结构体传参要传结构体的地址
如果传过去的是值,形参会在内存创建空间,浪费时间

三、结构体实现位段

1.位段的成员必须是整数类型(包括char、int等有符号/无符号类型)
2.位段名字后面有一个冒号(:)一个数字。

struct A
{
	int _a : 2;
	int _b : 30;
};//数字表示占的比特位的数量。

位段的内存分配

  1. 位段的空间是以一个int或char类型来开辟的
  2. 一个字节的内存从左往右还是从右往左是不确定的
  3. 剩余的空间不能满足下一个成员是否浪费不确定。
  4. 位段不支持跨平台
struct S
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};
struct S s = { 0 };
s.a = 10;//二进制是1010,因为是三个比特位,所以是010
s.b = 12;//1100,四个比特位
s.c = 3;//00011,五个比特位
s.d = 4;//0100,四个比特位

下面是图片
在这里插入图片描述
!!注意:
因为有的是多个位段在一个字节,所以不能用取地址符号
int位段被当成有符号还是无符号不确定
位段最大数不确定

四、联合体类型

1.联合体类型的声明、大小、特点

联合体也是由一个或者多个成员构成,这些成员可以是不同的类型。
但是编译器只给最大的成员分配空间,所以联合体是所有成员共用一块空间,所以也叫做:共用体。
例:

union un
{
	int a;
	char b;
};

联合体每个成员的起始地址是相同的
大小的计算:
1.联合的⼤⼩⾄少是最⼤成员的⼤⼩。
2.当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍。

union un
{
	int a;
	char b[7];
};//最大成员为7,最大整数倍为4,所以总大小为8.

五、枚举类型

枚举类型就是一一列举,{}中的内容也叫做枚举常量。
枚举类型的默认值是从0开始的,当然在初始化的时候也可以自己赋值,一旦自己赋值就不可以改了

enum Sex//性别
{
	MALE,//默认值为0
	FEMALE,//1
	SECRET=5}

优点

  1. 增加代码的可读性,一次可以定义多个
  2. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在数内使⽤,
  3. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。

总结

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值