C语言自定义数据类型的结构体、枚举和联合详解

结构体基础知识

首先结构体的出现是因为我们使用C语言的基本类型无法满足我们的需求,比如我们要描述一本书,就需要书名,作者,价格,出版社等等一系列的属性,无疑C语言的基本数据类型无法解决,所以就出现了最重要的自定义数据类型,结构体

首先我们创建一个书的结构体类型来认识一下

struct Book
{
	char name[20];
	char author[20];
	int price;
};

首先是struct是结构体关键字,用来告诉编译器你这里声明的是一个结构体类型而不是其他的东西,然后是Book是结构体标签,而关键字加标签就是你结构体类型的名字,即struct Book 是你结构体类型的名字,然后看到结构体里面的内容,即大括号里面的内容,有两个字符数组和一个整型变量,一个数组用来存放书的名字,一个数组用来存放书的作者,整型变量用来存放书的价格,在类型声明中需要多少变量就放入多少变量,需要什么变量就放入什么变量,而这些变量就是结构体的成员变量,成员变量可以是不同的类型注意,结构体声明的末尾分号不可省略,到此我们已经有了基本的认识,接下来我们来使用一下结构体类型,既然是类型,那么肯定就可以拿来创建变量,我们就拿上面那个描述书的结构体类型试一下

可以看到使用规则和基本数据类型之类的并无太大区别,唯一区别就是结构体初始化一定要用大括号将初始化的内容括起来,如果不是初始化那么就需要先访问他的成员才能一一赋值,这里我们是在创建结构体的时候对它进行了初始化,放入了一些数据,小伙伴们能够清楚的看到屏幕上输出了这些数据,其中通过结构体变量访问结构体成员的时候使用了点号. 这个点号是结构体成员访问操作符,通过它我们就可以拿到结构体的成员,看完之后小伙伴们最好是自己也敲一下试试,代码能力是练出来的,初学时一定要多敲多练,到此结构体基础知识我们就介绍完了,接下来我们来进阶一下。

结构体进阶知识

首先结构体是可以嵌套定义的,像下面这样

结构体计算大小

结构体在分配内存的时候,会发生结构体内存对齐,对齐规则如下:

  • 第一个成员在与结构体变量偏移量为0的地址处。
  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
  • 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
  • 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

知道了规则我们来用一下,下面这个结构体的大小不考虑对齐的情况只需要6byte的空间就能存下所有数据,但是考虑到内存对齐就需要12byte的空间,这就足足多了一倍的空间,那么为什么还需要这个对齐的规则呢,原因大致有以下两点:

  • 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
  • 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
struct S1
{
 char c1;//1 byte
 int i;//4byte
 char c2;//1byte
};
printf("%d\n", sizeof(struct S1));

总的来说,结构体的内存对齐是拿空间来换取时间的做法,结构体就介绍的差不多了,下面我们来看看枚举

枚举基础知识

枚举顾名思义就是把所有的可能性 一 一 列举出来,比如说一个星期分为星期一,星期二到星期天七天我们就可以使用枚举

enum Day
{
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};

和结构体一样首先是枚举关键字enmu然后是枚举的标签Day,然后是成员,但是和结构体不同的是,枚举的成员是常量,而且是整型常量,并且不赋值的话是有默认值,而且默认值是向下依次递增1的,我们来看看就知道了

可以看到不主动赋值的情况下,下一个比上一个大1,并且第一个默认为0,看看赋值了的

枚举就这么简单,接下来看看联合体

联合体

联合体是由关键字union和标签定义的,和结构体和枚举是一样的定义方式,和前面两个不一样的是,一个联合体只有一块内存空间,这句话什么意思呢,就相当于只开辟最大的变量的内存,其他的变量都在那个变量占据空间(空间可以被重叠占用)看看下面的图片

上面黑色和红色的重叠部分就是共用的区域,两个变量都能使用它,这个东西很少用的就不多讲了,唯一记住的就是,联合体可以求当前编译环境是大端字节序存储模式还是小端字节序存储模式,至于怎么求,看看下面这个代码,应该很好理解

#include<stdio.h>
union Un{
	char ch;
	int n;
};
int main()
{
	union Un un;
	un.n = 1;
	//小端 01 00 00 00
	//大端 00 00 00 01
	if (un.ch == 1) {//取出第一个字节的内容判断
		printf("小端");
	}
	else {
		printf("大端");
	}
	return 0;
}

这个东西理解不了也没啥关系,一般用不上。

一些小结和建议

1.尽量不要使用联合体,因为一次修改会导致多个数据被修改,容易出现不可预料的问题.

2.结构体内存对齐一定要学会计算,虽然实际可能用不上,但是可能会面试中出现.

3.结构体中还有一个叫字段的知识点,形式如下,这个东西现在用于传输数据,后端开发一般用不上,所以博主没讲,感兴趣的小伙伴就自行百度了解一下吧

4.枚举一般搭配switch语句使用,可以提高代码的可读性。

写在最后的话

到此这篇关于C语言自定义数据类型的结构体、枚举和联合详解的文章就介绍到这了,更多相关C语言自定义数据类型内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言自定义数据类型的结构体、枚举和联合详解

    结构体基础知识 首先结构体的出现是因为我们使用C语言的基本类型无法满足我们的需求,比如我们要描述一本书,就需要书名,作者,价格,出版社等等一系列的属性,无疑C语言的基本数据类型无法解决,所以就出现了最重要的自定义数据类型,结构体. 首先我们创建一个书的结构体类型来认识一下 struct Book { char name[20]; char author[20]; int price; }; 首先是struct是结构体关键字,用来告诉编译器你这里声明的是一个结构体类型而不是其他的东西,然后是Boo

  • C语言中的自定义类型之结构体与枚举和联合详解

    目录 1.结构体 1.1结构的基础知识 1.2结构的声明 1.3特殊的声明 1.4结构的自引用 1.5结构体变量的定义和初始化 1.6结构体内存对齐 1.7修改默认对齐数 1.8结构体传参 2.位段 2.1什么是位段 2.2位段的内存分配 2.3位段的跨平台问题 2.4位段的应用 3.枚举 3.1枚举类型的定义 3.2枚举的优点 3.3枚举的使用 4.联合 4.1联合类型的定义 4.2联合的特点 4.3联合大小的计算 1.结构体 1.1结构的基础知识 结构是一些值的集合,这些值称为成员变量.结构

  • Go语言学习之结构体和方法使用详解

    目录 1. 结构体别名定义 2. 工厂模式 3. Tag 原信息 4. 匿名字段 5. 方法 1. 结构体别名定义 变量别名定义 package main import "fmt" type integer int func main() { //类型别名定义 var i integer = 1000 fmt.Printf("值: %d, 类型: %T\n", i, i) var j int = 100 j = int(i) //j和i不属于同一类型,需要转换 fm

  • C语言程序中结构体的内存对齐详解

    目录 一.为什么存在内存对齐 二.结构体的内存对齐四规则 三.举例 一.为什么存在内存对齐 1.平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的:某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常. 2. 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐. 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问:而对齐的内存访问仅需要一次访问. 总的来说结构体的内存对齐是拿空间来换取时间的做法. 二.结构体的内存对齐四规则 默认情况:默认的对

  • go语言结构体指针操作示例详解

    目录 指针 go指针操作 不能操作不合法指向 new函数 指针做函数的参数 数组指针 结构体指针变量 结构体成员普通变量 结构体成员指针变量 结构体比较和赋值 结构体作为函数参数 指针 指针是代表某个内存地址的值.内存地址储存另一个变量的值. 指针(地址),一旦定义了不可改变,指针指向的值可以改变 go指针操作 1.默认值nil,没有NULL常量 2.操作符“&”取变量地址,“*“通过指针(地址)访问目标对象(指向值) 3.不支持指针运算,不支持“->”(箭头)运算符,直接用“.”访问目标成

  • Go结构体的基本使用详解

    目录 定义 实例化 匿名结构体 空结构体 构造函数 方法与接收者 匿名字段 实现面向对象的“继承”特性 标签tag 结构体与JSON系列化 本文主要介绍Go的结构体类型的基本使用,快速上车 定义 结构体,是一种自定义的数据类型,由多个数据类型组合而成.用于描述一类事物相关属性. 定义方式: type 类型名 struct { 字段名 字段类型 - } //示例: type Animal struct { Name string Age int } 实例化 结构体和结构体指针,两者的实例化有所区别

  • C++ 结构体初始化与赋值详解

    目录 1.结构体初始化 2.结构体赋值 参考文献 1.结构体初始化 结构体是常用的自定义构造类型,是一种很常见的数据打包方法.结构体对象的初始化有多种方式,分为顺序初始化.指定初始化.构造函数初始化.假如有如下结构体. struct A { int b; int c; }; (1)顺序初始化因为书写起来较为简约,是我们最常用的初始化方式,但相对于指定初始化,无法变更数据成员初始化顺序,灵活性较差,而且表现形式不直观,不能一眼看出 struct 各个数据成员的值. A a = {1, 2}; (2

  • Golang打印复杂结构体两种方法详解

    目录 fmt结构体占位符 打印复杂结构体 方案一 方案二 fmt结构体占位符 在Golang中有原生的 fmt 格式化工具去打印结构体,可以通过占位符%v.%+v.%#v去实现,这3种的区别如下所示: type User struct { Name string Age int } func main() { user := User{ Name: "张三", Age: 95, } fmt.Printf("%v\n", user) fmt.Printf("

  • C语言 结构体(Struct)详解及示例代码

    前面的教程中我们讲解了数组(Array),它是一组具有相同类型的数据的集合.但在实际的编程过程中,我们往往还需要一组类型不同的数据,例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放. 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为: struct 结构体名{     结构体所包含的变量或数组 }; 结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可

  • C语言热门考点结构体与内存对齐详解

    目录 一.引例 1.结构体的第一个成员永远放在结构体起始位置偏移量为0的位置 2.从第二个成员开始,总是放在偏移量为一个对齐数的整数处,对齐数=编译器默认的对齐数和变量自身大小的较小值 3.结构体的总大小必须是各个成员的对齐数中最大的那个对齐数的整数倍 二.小试牛刀 三.嵌套结构体的特殊情况 四.关于为什么存在内存对齐 1.平台原因(移植原因): 2.性能原因: 总结 一.引例 到底什么是结构体内存对齐,我们用一段代码来介绍一下 struct S1 { char c1;//1字节 int a;/

随机推荐