结构体、位段、枚举、联合体

前言

一、结构体

1.结构体的基本知识

2.结构体的声明

3.结构体的自引用

4.结构体变量的定义与使用

5.结构体的内存对齐

6.结构体传参

二、位段

(1)位段的声明和结构是类似的,有两个不同

(2)位段所占用的空间

(3)位段的跨平台

三、枚举

(1)枚举的定义

(2)枚举的优点

(3)枚举的使用

四、联合体

(1)联合体的定义

(2)联合体的特点

前言

结构体常被用于描述相对复杂的对象,其内容可以表示很多用单一数据无法表示的各种数据。

结构体类型不是由系统定义好的,而是需要程序设计者自己定义的。C语言提供了关键字struct来标识所定义的结构体类型。

一、结构体

1.结构体的基本知识

关键字struct和结构体名组合成一种类型标识符,其地位如同通常的int、char等类型标识符,其用途就像 int 类型标识符标识整型变量一样可以用来定义结构体变量。定义变量以后,该变量就可以像定义的其他变量一样使用了;成员又称为成员变量,它是结构体所包含的若干个基本的结构类型,必须用“{}”括起来,并且要以分号结束,每个成员应表明具体的数据类型。

2.结构体的声明

struct tag
{
 member-list; 
}variable-list;

例:一本书的声明

struct book
{
	int num;//字数
	char name[20];//书名
	char author[24];//作者
	char phouse[30];//出版社
};

再上述的条件上可以对结构体进行匿名声明,但结果会导致无法引用该结构体类型,要在另一个结构体中取出该结构体的成员地址时,编译器会直接弹出警告,因为这两个结构体是两个完全不同的类型,并不能直接提取地址。

3.结构体的自引用

(1)不使用typedef时

错误的方式:

struct tag
{
   struct tag;
   int value;
};

这种类型的声明是错误的,因为在调用这个结构体,在这个结构体的成员中还是会有结构体,会导致在内存分配的时候,因为其内容无限嵌套,导致内存无法为其分配相应的内存单位,从而导致程序的崩溃。

正确的方式:

​
struct tag
{
   struct tag* A;
   int value;
};

​

因为指针的长度是确定的(在32位的机器中指针的长度是4 type,在64位机器中指针的长度是8 type),所以编译器可以确定该结构体的长度。

4.结构体变量的定义与使用

(1)在定义结构体变量的时候,可以对其成员进行一定的初始化;也可以在声明这个结构体之后,对这个结构体类型的变量进行初始化。

   1.在声明定义的同时定义变量

​
struct book
{
	int num;
	char name[20];
	char author[24];
	char phouse[30];
};b1,b2

​

2.在声明定义结构体后,再定义该类型的变量

​
​
struct book
{
	int num;
	char name[20];
	char author[24];
	char phouse[30];
};

struct book b1,b2;

​

(2)引用结构体变量中成员的值:结构体变量.成员名。“.”是成运算符,在所有的运算符中的优先级最高。

  • 不能企图输出结构体变量名来输出结构体的所有成员,只能分别输出各个成员的值
  • 结构体变量成员可以像普通变量一样进行运算\n同类的结构体变量可以相互赋值
  • 可以引用结构体变量成员的地址,也可以引用结构体变量的地址,主要用作函数参数,传递结构体变量地址。

5.结构体的内存对齐

(1)结构体的对齐和补齐的规则:

对齐:结构体的第一个成员在结构体的地址偏移量为0的位置,每个成员的起始地址都是最大对齐数的整数倍地址处(对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值)。

补齐:结构体的总字节数必须是其对齐数的整数倍。

(2)修改默认对其数

#pragma pack(8)

这里是将默认对其数改为8.

#pragma pack()

这里是取消自己设置的默认对其数,并将其改为每个编译器自带的默认对其数。

6.结构体传参

结构体传参一般使用传地址的形式,这样有利于充分利用内存;如果使用传结构体的参数过去将会再重新创建一个临时的结构体变量来接受这个参数,这样可能会导致性能的丢失。

二、位段

(1)位段的声明和结构是类似的,有两个不同:
 1. 位段的成员必须是 int unsigned int 、 signed in和char类型
 2. 位段的成员名后边有一个冒号和一个数字。
(2)位段所占用的空间:
位段所占用的空间按照需要以4个字节或者1个字节来进行开辟的。
(3)位段的跨平台
位段一般不支持跨平台使用,因为位段的最大数目并不能确定,并且涉及位段的应用并未有相应的官方定义,所以会涉及很多问题。

三、枚举

(1)枚举的定义

enum Day//星期
{
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};
其中{}中的内容是枚举类型的可能取值,也叫作 枚举常量。
这些内容可能都是有值的,默认从 0 开始,依次递增 1 ,在定义的时候也可以赋初值,后面的值随之变化在其基础上进行递增1。
(2)枚举的优点
1. 增加代码的可读性和可维护性
2.使用方便,可以一次定义多个变量
3.#define定义的标识符在进行代码编辑的时候会将相应的标识符都转化为相应的数,但枚举常量还保留相应的标识符,更利于识别相应的内容。
(3)枚举的使用
在使用枚举常量的时候,如果要将其赋值,必须要使用相应的枚举常量为其赋值。

四、联合体

(1)联合体的定义

//联合类型的声明
union Un
{
 char c;
 int i;
};
//联合变量的定义
union Un un;

(2)联合体的特点

1.联合体中的成员是公用一块空间的,所以联合体的大小至少是其联合的最大成员的大小(因为联合体至少有能力去保存最大成员的地址)。

2.当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值