C语言自定义类型超详细梳理之结构体 枚举 联合体

目录
  • 一、什么是结构体
    • 1.结构体实现
    • 2.匿名结构体类型
    • 3.结构体自引用
    • 4.结构体的内存对齐
    • 5.结构体位段
  •  二、什么是枚举
    • 1.枚举类型的定义
    • 2.枚举的优点
  • 三、联合(共用体)
    • 1.什么是联合(共用体)
    • 2.联合(共用体)的定义
    • 3.联合(共用体)的初始化
  • 总结

一、什么是结构体

结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。

//结构体声明
struct tag //struct:结构体关键字,tag:标签名,合起来是结构体类型(类型名)
{
	member - list;//大括号里面的是结构体成员变量
}variable - list;//结构体变量

1.结构体实现

代码如下:

#include<stdio.h>

struct Book
{
	char name[20];//书名
	int price;//价格
	char id[20];//书号
}b2,b3,b4;//结构体变量(全局变量)
int main()
{   //结构体变量(局部变量)
	struct Book b1 = { "c和指针", 30, "1112345454" };//结构体初始化
	struct Book* pb = &b1;
	printf("%s %d %s\n",b1.name,b1.price,b1.id );
	printf("%s %d %s\n", pb->name, pb->price, pb->id);//指针方式打印

	return 0;
}

2.匿名结构体类型

//匿名结构体类型
struct
{
 int a;
 char b;
 float c;
}s;//直接永匿名结构体类型创建了一个变量s,匿名结构体只能用一次

struct
{
 int a;
 char b;
 float c;
}*ps;//匿名结构体的指针

结构在声明的时候省略掉了结构体标签(tag)就叫做匿名结构体。

那么问题来了?
int main()
{
  ps = &s;//不合法,编译器会把上面的两个声明当成完全不同的两个类型。
所以是非法的
}

3.结构体自引用

struct Node
{
    int data;
    struct Node* next;
}
//结构体自引用
//这个节点能够找到同类型的下一个节点,这就叫结构体的自引用,我自己能找到同类型跟自己同类型的下一个元素就叫结构体的自引用。
//结构体的自引用实现:在结构体里面包含同类型的结构体的指针。

4.结构体的内存对齐

首先得掌握结构体的对齐规则:

1. 第一个成员在与结构体变量偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8

3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

我们来算一下上面结构体S内存大小为什么是12个字节

我用到编译器是vs,vs编译器的默认对齐数是8.

1.结构体的第一个成员,放在结构体变量在内存中储存位置的0偏移处开始。

2.从第二个成员往后的所有成员,都放在一个对齐数(成员的大小和默认对齐数的较小值)的整数的整数倍的地址处。

3.结构体的总大小是结构体的所有成员的对齐数中最大的那个对齐数的整数倍。

5.结构体位段

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

1.位段的成员必须是 int、unsigned int 或signed int 。

2.位段的成员名后边有一个冒号和一个数字。

假设我们用二进制的方式来表示性别,分为男、女、保密。可以用00、01、10分别表示。这样我们连一个字节的大小都用不到,但如果我们创建变量,一个int变量就占四个字节,所以说位段在一定程度上节省了空间。

位段的内存分配

1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型

2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。

3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

 二、什么是枚举

性别有:男、女、保密,也可以一一列举。

月份有12个月,也可以一一列举

这里就可以使用枚举了。

枚举是要创造出一种新的类型,这种类型的取值是非常有限的,明确的只有那么几种可能取值,我们就可以用枚举来创造一个枚举类型

枚举类型的大小就是4.

1.枚举类型的定义

#include<stdio.h>
//声明枚举类型
enum Color//enum枚举关键字,Color枚举类型,
{
	RED,//大括号里面放的是枚举的可能取值(常量)
	GREEN,
	BLUE
};
int main()
{
	enum Color c = BLUE;
	return 0;
}

大括号里面这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。

enum Color//颜色
{
 RED=1,
 GREEN=2,
 BLUE=4
};

2.枚举的优点

我们可以使用 #define 定义常量,为什么非要使用枚举?

枚举的优点:

1. 增加代码的可读性和可维护性

2. 和#define定义的标识符比较枚举有类型检查,更加严谨。

3. 防止了命名污染(封装)

4. 便于调试

5. 使用方便,一次可以定义多个常量

三、联合(共用体)

1.什么是联合(共用体)

联合也是一种特殊的自定义类型 这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。

2.联合(共用体)的定义

//联合类型的声明
union Un
{
 char c;
 int i;
};
//联合变量的定义
union Un un;
//计算连个变量的大小
printf("%d\n", sizeof(un));

计算联合(共用体)的大小

 这里为什么算出的结果是4呢,我们看下图:

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联 合至少得有能力保存最大的那个成员)。

3.联合(共用体)的初始化

#include<stdio.h>

union Un
{
	char c;
	int i;
};
int main()
{
	union Un u = { 10 };//初始化
	u.i = 1000;//成员变量单独初始化
	u.c = 100;
	printf("%p\n",&u );
	printf("%p\n", &(u.c));
	printf("%p\n", &(u.i));
	return 0;
}

总结

这样就简单介绍完了结构体,枚举和联合体的定义,初始化,和简单的使用。写的比较潦草,如果上述文章有任何问题 ,欢迎大佬们提出质疑,我会虚心学习和改正,最重要的是能共同进步,共同成长,学习好编程。

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

(0)

相关推荐

  • C语言结构体指针引用详解

    目录 指向结构体变量的指针 指向结构体数组的指针 结构体指针,可细分为指向结构体变量的指针和指向结构体数组的指针. 指向结构体变量的指针 前面我们通过"结构体变量名.成员名"的方式引用结构体变量中的成员,除了这种方法之外还可以使用指针. 前面讲过,&student1 表示结构体变量 student1 的首地址,即 student1 第一个项的地址.如果定义一个指针变量 p 指向这个地址的话,p 就可以指向结构体变量 student1 中的任意一个成员. 那么,这个指针变量定义成

  • C语言中结构体实例解析

    目录 一.结构体定义 二.实例演示 结构体作为函数参数 结构体指针 三.typedef struct 和 struct的区别 1.声明不同 2.访问成员变量不同 3.重新定义不同 总结 一.结构体定义 C语言结构体由一系列相同或者不同类型的数据构成的集合,结构体类型就是以struct关键字定义的数据类型. 结构体的格式如下: struct 结构名称 { 结构体所包含的数据成员,包括变量数组等 } 结构变量 ;//结构变量可以指定一个或多个 举例: struct Student { char na

  • 一起来看看C语言世界中的结构体

    目录 一.结构体的概念: 二.结构体变量的定义和初始化 结构体变量的定义 (1)单独定义 (2)混合定义(在定义结构体的同时定义结构体变量) 结构体变量的初始化 三.结构体变量的使用("."与"->"的使用) (1)"."的使用(1级运算符,结合方向从左到右): (2)"->"的使用(1级运算符,结合方向从左到右): 总结 一.结构体的概念: 结构体是由一批数据聚合而成的结构型数据. 引入结构体,程序设计人员就可以

  • C语言的结构体你了解吗

    目录 结构体内存对齐 结构体传参 结构体实现位段 什么是位段 位段在内存中的存储 位段的问题 总结 结构体内存对齐 当我们创建一个结构体变量时,内存就会开辟一块空间,那么在创建结构体变量时内存到底是怎么开辟空间的呢?会开辟多大的空间呢?我们来看一下下面的代码 struct S { int i; char c; char b; }; struct G { char c; int i; char b; }; int main() { struct S u; struct G g; printf("%

  • C语言结构体详细图解分析

    目录 结构体 结构体的声明 结构体变量的定义和初始化 结构体大小计算 结构体 结构是一些值的集合,这些值称为成员变量.结构的每个成员是不同类型的变量. 为什么要有结构体 比如说,描述一个学生时,需要有 名字 性别 年龄 身高 来一起描述,需要不同的变量,便有了结构体类型来描述 结构体的声明 struct tag { member-lest//成员列表 }variable-list;//变量列表 例如一个学生 struct stu { char name[20]; char sex[5]; int

  • C语言结构体的全方面解读

    目录 前言 一.结构体的声明与定义 1.结构体的声明 2.结构成员的类型 3.结构体的定义 二.初始化结构体 三.访问结构体成员 四.结构体嵌套 五.结构体指针 六.结构体传参 总结 前言 C语言提供了不同的数据类型,比如说int.float.double.char等,不同的类型决定了一个变量在内存中应该占据的空间以及表现形式. 但是,当我们定义一个人的时候,人的不同属性就比较难用同一个数据类型来定义了,因为人的身高.年龄.体重等属性往往需要不同数据类型,在这个时候,我们便引入结构体这个概念.

  • 深入浅出理解C语言初识结构体

    目录 1.定义和使用结构体变量 结构体的基础知识 自己建立结构体类型 struct 结构体名 类型名 成员名: 声明结构体的形式 结构体的初始化 2. 结构体成员的访问 3.结构体传参 1.定义和使用结构体变量 结构体的基础知识 结构是一些值的集合,这些值称为成员变量.结构的每个成员可以是不同类型的变量. 自己建立结构体类型 结构的成员可以是标量.数组.指针,甚至是其他结构体. struct 结构体名 {成员表列}:↓ 注意:结构体类型的名字由一个关键字 struct 和结构体名组合而成的(例如

  • C语言自定义类型超详细梳理之结构体 枚举 联合体

    目录 一.什么是结构体 1.结构体实现 2.匿名结构体类型 3.结构体自引用 4.结构体的内存对齐 5.结构体位段  二.什么是枚举 1.枚举类型的定义 2.枚举的优点 三.联合(共用体) 1.什么是联合(共用体) 2.联合(共用体)的定义 3.联合(共用体)的初始化 总结 一.什么是结构体 结构是一些值的集合,这些值称为成员变量.结构的每个成员可以是不同类型的变量. //结构体声明 struct tag //struct:结构体关键字,tag:标签名,合起来是结构体类型(类型名) { memb

  • C语言 语义陷阱超详细梳理总结

    目录 1 指针与数组 2 非数组的指针 3 作为参数的数组声明 4 空指针并非空字符串 5 边界计算与不对称边界 6 求值顺序 7 整数溢出 8 为函数提供返回值 1 指针与数组 C语言中只有一维数组.数组中的元素可以是任意类型的对象,这也是多维数组构建的理论基础所在 对于一个数组,我们只能做两件事:确定该数组的大小以及获得该数组下标为0的元素的指针.任何一个数组下标运算都等同于一个对应的指针运算. 数组名代表首元素的地址,无法对其进行++或者–操作,换句话说,我们无法改变数组名(表示的值),因

  • 详解C语言结构体,枚举,联合体的使用

    目录 一.匿名结构体 二.结构体的自引用 1.声明时不要自己引用自己 2.结构体重命名时不能使用重命名 三.结构体内存对齐规则 1.结构体内存计算 2.结构体嵌套 3.通过调整结构体成员顺序,压缩内存 四.存在内存对齐的原因 五.修改默认对齐数 六.结构体传参 七.位段 1.位段在内存中的存储 2.位段的跨平台问题 八.枚举 1.枚举的定义 2.枚举的优点 九.联合体(共用体) 1.联合体大小的计算 2.使用联合体判断计算机的大小端字节序 一.匿名结构体 struct { char name[2

  • C语言结构体,枚举,联合体详解

    目录 1.什么是结构体.枚举.联合体 2.定义结构体 2.1 包含结构体成员变量.variable 2.2 tag.结构体成员变量 2.3 用结构体声名变量 2.4 用typedef 创建新类型 2.5 两个结构体相互包含 2.6 结构体变量初始化 2.7 结构体指针 3.枚举 3.1 定义方式 3.2 为什么用枚举 3.3 枚举变量的定义 3.4 实例 3.5 枚举实际用途 4.联合体 4.1 与结构体区别 4.2 定义 总结 1.什么是结构体.枚举.联合体 结构体(struct)是由一系列具

  • C语言超详细梳理排序算法的使用

    目录 排序的概念及其运用 排序的概念 排序运用 插入排序 直接插入排序 希尔排序 选择排序 直接选择排序 堆排序 交换排序之冒泡排序 总结 排序的概念及其运用 排序的概念 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作. 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次 序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排 序算法

  • C语言 超详细梳理总结动态内存管理

    目录 一.为什么存在动态内存分配 二.动态内存函数的介绍 1.malloc和free 2.calloc 3.realloc 三.常见的动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟的空间使用free释放 4.使用free释放一块动态开辟空间的一部分 5.对同一块开辟的空间多次释放 6.动态内存开辟忘记释放(内存泄漏) 四.几个经典的笔试题 一.为什么存在动态内存分配 我们已经掌握的内存开辟方式有: int a = 10://在栈空间开辟4个字节的连续

  • C++ 超详细梳理继承的概念与使用

    目录 继承的概念及定义 继承的概念 继承定义 定义格式 继承关系和访问限定符 继承基类成员访问方式的变化 基类和派生类对象赋值转换 继承中的作用域 派生类的默认成员函数 继承与友元 继承与静态成员 复杂的菱形继承及菱形虚拟继承 菱形继承 虚拟继承解决数据冗余和二义性的原理 继承的总结和反思 继承的概念及定义 继承的概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类.继承呈现了面向对象程序设计的层次结构,体

  • Java超详细梳理异常处理机制

    目录 一.异常概述与异常体系结构 1. 异常概述 引入 概念 2. 分类 2.1 Error vs Exception 2.2 编译时异常vs运行时异常 3. 常见异常 3.1 分类 3.2 代码演示 二.异常处理机制 1. 概述 2. 异常处理机制一之try-catch-finally 2.1 语法格式 2.2 使用 2.3 代码演示 3. 异常处理机制二之声明抛出异常throws 3.1 语法格式 3.2 使用 4. try-catch-finally与throws的区别 5. 手动抛出异常

  • Java超详细梳理IO流的使用方法上

    目录 Java语言的输入输出类库 1.流的概念 2.流的分类 3.流的作用 4.输入输出流类库 使用InputStream和OutputStream流类 1.基本输入输出流 1.InpitStream流类 2.OutputStream流类 2.输入输出流的应用 2.1文件输入输出流 2.2顺序输入流 2.3管道输入输出流 2.4过滤输入输出流 2.5标准输入输出 你要学会: 流的概念 处理字节流的类 处理字符流的类 Java标准输入输出 文件管理类 Java语言的输入输出类库 1.流的概念 流是

  • C语言超详细讲解结构体与联合体的使用

    目录 结构体 offsetof-宏 位段 枚举 联合体(共用体) 结构体 结构体内存对齐问题: 当我们在计算结构体的大小时,我们便需要清楚的知道结构体内存对齐是什么. 存在内存对齐的原因可细分为两个: 平台原因: 不是所有的硬件平台都能方位任意地址上的任意数据:某些硬件平台只能在某些地址处取某些特定类型的数据,否则会抛出硬件异常. 性能原因: 首先内存对齐可以提高程序的性能,当访问未对其的内存空间时,有时候处理器需要进行两次访问,而当访问对齐的内存时,只需要一次就够了.这同时也被叫做 用空间换取

随机推荐