【C语言】自定义类型详解:结构体、枚举、联合体

Tube-based MPC完全指南:RCI集合构造与Matlab实现 模型预测控制(MPC)在实际工程中常因模型失配和外部扰动导致硬约束被突破,而鲁棒控制中的Tube-based MPC通过将单条预测轨迹扩展为“管道”集合,为不确定性提供了严格的安全边界。其核心在于利用鲁棒控制不变集(RCI)离线构造安全域,再结合在线标称MPC与反馈校正实现约束的硬保证。针对非线性系统,利普希茨条件为等效扰动的放大和RCI的构造提供了理论基础,使得算法既能保留非线性描述,又不牺牲在线计算效率。该方法适用于带扰动和参数漂移的机械系统、过程控制及嵌入式控制场景。本文以摩擦力非线性系统为例,从RC 阅读详情

目录

一、结构体详解

1、结构体类型的声明

1.1.结构体是什么?

1.2.结构体声明

1.3.特殊的结构体声明(匿名结构体)

2、结构体的自引用

3、结构体变量的定义和初始化

4、结构体的内存对齐

内存对齐的规则是什么呢?

列1:

列2:

列3:

列4.内嵌结构体:

宏offsetof

#pragram pack()

 为什么会出现内存对齐?

5、结构体传参

6、结构体实现位段(填充&移植)

1.什么是位段?

2.位段的内存分配

3.位段跨平台的具体问题

4.位段的运用

二、枚举详解

1)、枚举类型的定义

2)、枚举的优点

3)、枚举的使用

三、联合体详解

1)、联合体类型的定义

2)、联合体类型的特点

3)、联合体的大小计算


一、结构体详解


1、结构体类型的声明


1.1.结构体是什么?

结构体是用来定义一个复杂对象,其关键字:struct

1.2.结构体声明

如果我们需要来描述一本书:书名、价格、序号

struct Book
{
	char name[20];// 书名
	int price;// 价格
	int list;// 序号
};//这就是我们声明的一个书的类型

同时我们可以在声明时定义一个变量

struct Book
{
	char name[20];// 书名
	int price;// 价格
	int list;// 序号
}bk1;// 我们定义了一个结构体变量 变量名是bk1

1.3.特殊的结构体声明(匿名结构体)

如果我们在声明时没有给这个类型附加类型名,那么这就是一个匿名结构体。

注意:如果我们定义的是一个匿名结构体,那么我们只能在声明时定义变量,以后就不能在使用这个匿名结构体去定义变量了。

struct
{
	char a;
	int b;
	short c;
}x;// 这就是一个匿名结构体,注意匿名结构体只能被使用一次

为了区分一下特殊情况看看如下代码:

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

struct sct
{
	char a;
	int b;
	short c;
}*p;定义了一个结构体指针

p = &x;//正确吗??可以这样用吗??

答案是不正确的,这两个结构体虽然成员的类型是一样的,但是编译器会将其区分为两个结构体类型,而两给个不同的类型的指针是不能赋值的。


2、结构体的自引用


定义:自引用就是在结构体的内部,有一个成员类型是这个结构体的指针。

struct Node
{
	int val;
	struct Node* next;
};// 这个结构体里面有一个自己的指针

那么可不可以将其成员写成自己这个结构体类型呢?不行,编译器不知道到底应该分配多少空间给这个结构体。

struct Node
{
	int val;
	struct Node next;
};// 这样是不行的,结构体里面有结构体,然后这个结构体里面又有结构体………………这样
  //编译器就不知道到底该为这个结构体分配多少空间了。

技巧:我们定义一个结构体变量时,总是会反复的写重复的关键字,我们可以typedef这个类型,方便我们以后定义变量时,编写迅速

typede fstruct Node
{
	int val;
	struct Node* next;
}Node;// 将这个结构体类型名重定义为 Node

那么我们在自引用时可不可以直接写重定义的类型名呢?

typedef struct Node
{
	int val;
	Node* next;
}Node;// 这样时不行的,这时会有一个经典的问题:是先有鸡,还是现有蛋。
     // 这里也是,是先有这个结构体,还是先重定义。

3、结构体变量的定义和初始化


在声明时定义&在普通定义

struct Book
{
	char name[20];// 书名
	int price;// 价格
	int list;// 序号
}bk1;

struct Book bk2;

初始化

struct Book
{
	char name[20];// 书名
	int price;// 价格
	int list;// 序号
}bk1;

struct Book p = { "mane", 75, 1 };

嵌套初始化

struct Book
{
	char name[20];// 书名
	int price;// 价格
	int list;// 序号
}bk1 = { "name", 75, 2};

struct Book
{
	char name[20];// 书名
	int price;// 价格
    struct Book p;
	int list;// 序号
}bk1;

bk1 = { "name", 75, {"n", 60, 1}, 2 };

4、结构体的内存对齐


每一种类型都会有自己的大小,比如int占4个字节,char占1一个字节,结构体类型也是,但是结构体的成员的不固定的,其大小也是不固定的,并且有自己的一套大小计算方法(内存对齐)。

// vs结构体默认对齐数是8
struct S
{
	char ch;// 8 -> 1
	int i;// 8 -> 4
	char c;// 8 -> 1
};// 内存:12字节

内存对齐的规则是什么呢?

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

2、其他成员要对齐到这个成员的对齐数的整数倍偏移量地址处。

(成员的对齐数:默认对齐数 与 这个成员的大小 相比较的较小值)

 (首先:我们需要知道默认对齐数。(vs编译器中是8))

3、结构体的总大小为 成员最大对其数的整数倍

4、如果嵌套了结构体成员p,那么这个嵌套结构体成员p的对齐数就等于这个结构体p的成员的最大对齐数。

列1:

// vs结构体默认对齐数是8
struct S
{
	char ch;// 8 -> 1
	int i;// 8 -> 4
	char c;// 8 -> 1
};// 内存:12字节

图解1:

 

列2:

struct S1
{
	int i;// 8 -> 4
	char ch;// 8 -> 1
	char c;// 8 -> 1
};// 内存:8字节

图解2:

 

列3:

struct S2
{
	char ch;// 8 -> 1
	int i;// 8 -> 4
	double b;// 8 -> 8
};// 内存:16字节

图解3:

列4.内嵌结构体:

struct S2
{
	char ch;// 8 -> 1
	int i;// 8 -> 4
	double b;// 8 -> 8
};// 内存:16字节

struct S3
{
	char ch;// 8 -> 1
	struct S2;// 8 -> 8
	double b;// 8 -> 8
};// 内存:32字节

 图解4:

 

 

宏offsetof

如果我们不确定自己所求的成员偏移量,我们可以利用offsetof这个宏,将一个结构体的成员偏移量打印出来:

其参数是这个结构体类型,其成员名

struct S3
{
	char ch;// 8 -> 1
	struct S2 s;// 8 -> 8
	double b;// 8 -> 8
}c;// 内存:32字节
int main()
{
	printf("%u\n",offsetof(struct S3, s));


    return 0;
}

#pragram pack()

vs中默认对其数是8,如果我们需要可以将其修改为我们所需要的对齐数


struct S2
{
	char ch;// 8 -> 1
	int i;// 8 -> 4
	double b;// 8 -> 8
};// 内存:16字节

#pragma pack(1) // 将默认对齐数修改为1
struct S3
{
	char ch;// 8 -> 1
	struct S2 s;// 8 -> 1
	double b;// 8 -> 1
}c;// 内存:1 + 16 + 8 = 25字节

 为什么会出现内存对齐?

1、平台(移植)原因:并不是所有的硬件都可以在任何地址上存放内容的,一些硬件只能在某一些地址处取地址,否则硬件就会报出错误

2、性能原因:在访问内存的时候,由于处理器是32位的,一次处理32个位,如果内存不对齐,就有可能一个数据需要在内存中去取两次的情况

总结:拿空间换时间

5、结构体传参


1、值传递

直接将这个结构体变量实参传给函数

这样做是不好的,调用函数时会发生压栈的操作,而值传递一个结构体,这个结构体占用内存较大,就会过多的耗损空间和时间,增大系统开销,所以我们尽量采用指针传递。

2、指针传递

将这个结构体的指针传给函数,不管什么指针,只要是指针就只会占用四个字节


6、结构体实现位段(填充&移植)


1.什么是位段?

位段和结构体相识有些许的不同

i.位段的成员只能是 int, unsigned int, char

ii.位段成员后面有一个冒号(:)

struct A
{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};

2.位段的内存分配

i.位段的成员是int /unsigned int/char

ii.开辟的空间是按照需要以四字节或者一字节来开辟的

iii.位段空间分配会涉及到很多内容,所以位段是不跨平台的

struct A
{
	int _a : 2;// 2 个bit位
	int _b : 5;// 5 个bit位
	int _c : 10;// 10 个bit位
	int _d : 30;// 30 个bit位
};// 8字节

成员冒号后面的值表示这个成员占用多少bit位,最大不得超过这个成员的最大值,这里不能超过32,在vs环境下,当当前开辟的空间剩余的bit不能容纳下一个成员时,会开辟一个新的4字节空间。

 

3.位段跨平台的具体问题

i.int 被当作有符号还是无符号是不确定的

ii.位段中最大位数不能确定。(16位机器下int十六位,32位机器下int三十二位)

iii.位段成员是由左到右还是从右到左分配没有规定

iiii.当结构不能容纳下一个成员时,是舍弃当前剩余bit位,还是不舍弃,不确定

4.位段的运用

比如网络ip地址就是运用的位段

 


二、枚举详解

枚举就是一一列举


1)、枚举类型的定义


关键字:enum

enum Day//星期
{
 Mon,// 0
 Tues,// 1
 Wed,// 2
 Thur,// 3
 Fri,// 4
 Sat,// 5
 Sun //8
};// 这个成员的值实际上就是 由0开始依次递增的值
enum Sex//性别
{
 MALE,
 FEMALE,
 SECRET
};
enum Color//颜色
{
 RED,
 GREEN,
 BLUE
};

2)、枚举的优点


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

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

3. 防止了命名污染(封装) 4. 便于调试

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


3)、枚举的使用


enum Day//星期
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};
int main()
{
	enum Day d = Wed;

	return 0;
}

我们可以将枚举成员设置初始值

enum Day//星期
{
	Mon = 5,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};

但我们不可以对这些成员再赋值

enum Day//星期
{
	Mon = 5,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};


Wed = 4;//这是错误的

三、联合体详解

联合体成员公用一块空间


1)、联合体类型的定义

关键字:union

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


2)、联合体类型的特点


联合体成员共用一块空间

union Un
{
 int i;
 char c;
};
union Un un;
// 下面输出的结果是一样的吗?
printf("%d\n", &(un.i));
printf("%d\n", &(un.c));
//下面输出的结果是什么?
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);

前面两行表示,成员共用一块内存

第三行表示,成员之间会相互影响

所以联合体一般一次只使用一个成员


 

3)、联合体的大小计算

1.联合体的大小至少是最大成员的大小

2.当最大成员大小不是最大对齐数大小的整数倍时,就要对齐到最大对齐数的整数倍


union Un1
{
 char c[5];// 8 -> 1
 int i;// 8 -> 4
};// 8 字节
union Un2
{
 short c[7];// 8 -> 2
 int i;// 8 -> 4
};// 16字节
//下面输出的结果是什么?
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));

 


 

Python量化交易实战:如何用vnpy+Tushare获取股票历史数据(附完整代码) 本文详细介绍了如何利用vn.py框架与Tushare数据接口,构建一个健壮的Python量化交易数据获取引擎。通过封装Tushare API,实现股票历史数据的自动化获取与格式转换,并适配vn.py的BarData结构,为策略回测与实盘交易提供稳定、高效的数据基础。文中提供了完整的代码实现,涵盖环境配置、核心封装逻辑及高级功能扩展。 阅读详情

相关推荐

高分7(GF7)卫星数据制作平原地区DSM/DEM(三)——可信度分割

李国春(接上)

副组长的博客 1715

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

结构体、枚举、联合体1.什么是结构体、枚举、联合体2.定义结构体2.1 包含结构体成员变量、variable2.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)是由一系列具有相同类型或不同类型的数据项构成的

Ja_king_的博客 4281

基于FPGA的示波器设计

ADC 、DAC、FPGA、LCD液晶、示波器

FDL_AQ的博客 1万+

结构体,联合体,枚举详解

结构体,联合体,枚举详解 目录 结构体 联合体 枚举常量 1.结构体 在C语言中,系统已经提供了一些数据类型,比如float,int,double,char等,但是我们有时会需要更复杂的类型来描述一个数据。假如我想描述一个学生,我需要知道他的学号,姓名,性别,那么我就需要三个类型来分别保存他的信息,到时候需要信息时还得分别查找,显然这是不方便的。因此有了结构体,我们可以根据自己所需来定义数据类型。 简言之,结构体是由不同的类型数据组成的组合型数据结构。 结构体类型的声明以及定义 struct 结构

lyzzs222的博客 2098

HC32F460的GPIO重映射实战:如何用3步搞定SPI引脚冲突问题

本文详细介绍了HC32F460的GPIO重映射功能,通过三步操作解决SPI引脚冲突问题。文章解析了HC32F460的FuncGroup功能分组机制,提供了具体的寄存器配置步骤和验证技巧,并对比了与传统方案的性能优势,帮助工程师灵活配置引脚,优化硬件设计。

t4y5u6i7o的博客 918

避免踩坑!杰理AC63蓝牙名修改常见问题及解决方案(含BLE后缀处理)

本文详细解析了杰理AC63蓝牙设备名称修改的全过程,包括基础操作、BLE后缀处理及高级调试技巧。针对蓝牙名修改中的常见问题,提供了实用的解决方案和代码示例,帮助开发者避免踩坑并实现高效定制。

q6r7s8t9的博客 413

自定义类型:结构体、枚举、联合

结构体,枚举,联合

my_heart_goon的博客 434

InvocationException: GraphViz‘s executables not found【BUG已解决】

在机器学习框架中遇到了一个bug:安装了GraphViz模块后,在对着sklearn的决策树文档操作输出决策树模型结果时,还是爆出了如下的错误: 报错位置为: 报错语句为:网上很多答案告诉我们,要我们安装GraphViz模块,然而并不对! 如下,我安装了GraphViz,但是还是报错了。 所以说问题不在这,我查阅质料发现,改正这个bug的方法有一个:下文详细描述。解决bug为: 1.去graphviz.官方下载自己电脑符合的操作系统的安装包:2,安装的时候,记住自己安装在电脑里的位置:以我的电脑为例,我的

一键难忘的博客 3968

C语言 | 自定义类型(结构体/联合体/枚举)

结构体变量的定义有如下两种;//1、声明同时定义struct A{int a;char ch;}x1;//1、声明后定义结构体变量的初始化也有如下两种;//1、声明同时初始化struct B{int b;char ch;//2、定义变量时初始化//枚举星期enum Day{Mon,Tues,Wed,Thur,Fri,Sat,Sun};//枚举颜色enum Color{Red,Green,Yellow};

Nice_W的博客 1598

SpringAI系列 - MCP篇(二) - MCP Server Boot Starter

此处需注意之前的。

罗小爬的技术宝书 1320

图文:银行核心账务处理逻辑(白话篇)

银行账务系统分为对内账(记录银行自身资产负债)和对外账(处理客户交易),通过特定编码规则的账号体系进行管理。采用T型账户结构和凭证制度确保每笔交易可追溯,通过明细核算与综合核算双线并行、每日轧账核对(科目日结单、总账、日计表)实现账务精准平衡。从业务触发到最终账平的全流程体现了银行账务"分层记录、双向核对、闭环校验"的核心原则,保障资金流动的透明性与安全性。

银行信息系统应用架构详解 541

自定义类型详解:结构体,枚举,联合

自定义类型详解:结构体(struct),枚举(enum),联合(union)

qq_55383558的博客 927

适航规章、标准,书籍资料下载汇总(更新中)

以下是一些收集到的适航相关的资料,分享给大家。(如果没有你想要的资料,请留言,等找到会及时更新!

qq_41854911的博客 2560

[C语言]自定义类型详解:结构体、联合体、枚举

int x;int y;}s1;//声明类型的同时定义变量s1//定义结构体变量s2//结构体嵌套初始化int n;int main()enum Day//星期Mon,Tues,WedThur,Fri,Sat,Sunenum Sex//性别MALE,FEMALE,SECRET。

2401_83283514的博客 1902

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

C语言详解——自定义类型:结构体、枚举、联合体

你学过结构体、枚举、联合体吗?如果没学过就来我这里看看吧

VHhhbb的博客 1099

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

【c语言】自定义类型:结构体,枚举,联合体详解

有了结构体类型,那如何定义变量,其实很简单int x;int y;}p1;//声明类型的同时定义变量p1//定义结构体变量p2//初始化:定义变量的同时赋初值struct Stu //类型声明//名字int age;//年龄//初始化int data;//结构体嵌套初始化//结构体嵌套初始化位段的声明和结构是类似的,有两个不同:位段的成员必须是int或signed int 或者char。位段的成员名后边有一个冒号和一个数字。比如:A就是一个位段类型。

m0_74910646的博客 233

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

C语言自定义类型详解:结构体、联合体与枚举

C语言除了提供基本数据类型(如int、char、float等)外,还允许用户自定义数据类型。自定义类型包括结构体(struct)联合体(union)和枚举(enum),它们是构建复杂程序的重要工具。本文将系统讲解这三种自定义类型的声明、使用、内存布局以及最佳实践。结构体的声明、初始化和内存对齐规则位段的概念和使用场景联合体的特点和内存共享机制枚举的优势和使用方法位段(Bit-field)允许按位分配内存,节省空间。成员必须是intsigned int(C99也支持char等)

2401_89060340的博客 354

C语言自定义类型:结构体(struct)、联合体(union)和枚举类型(enum)详解

在C语言中,自定义类型是程序员根据实际需求定义的新型数据结构,包括结构体(struct)、联合体(union)和枚举类型(enum)。这些类型能够帮助程序员更好地组织和管理数据,使代码更具可读性和可维护性。理解这些自定义类型及其相关的内存对齐等知识点,对于掌握C语言的高级应用至关重要。

My__Space的博客 830

C语言:自定义类型 - 结构体 & 联合体 & 枚举

讲解C语言的自定义类型,包括结构体,联合体,枚举

博客网站 https://async-area.com 1720

C语言之自定义类型:结构体、联合体和枚举

本篇文章对C语言中的结构体、联合体和枚举类型进行了全面的解释,包含类型声明、变量创建和内存对齐等内容

Eristic0618的博客 1253

【C语言】自定义类型的介绍(结构体,枚举,联合体,位段)

在C语言当中,除了我们常用的几个基本的数据类型之外,还有一种类型叫自定义类型。比如:我们要描述一个学生。这个学生有姓名,性别,年龄,身高等。单独用基本的数据类型是不能完全描述的。这个时候就要使用我们自定义的类型来进行描述。自定义的类型有结构体,枚举和联合体。 C语言 数组允许定义可存储相同类型数据项的变量,结构是C语言编程中另一种用户自定义的可用的数据类型,它允许存储不同类型的数据项。结构体是一些值的集合,这些值被称为成员变量,每一个成员变量可以有不同的类型。结构体的声明与定义 其中是自定义结构体类型,..

杨同学的博客 3517

教你学会自定义类型:结构体、枚举、联合体

系列文章目录 文章目录系列文章目录前言一、结构体是什么1.结构体的定义:2.结构体的实现:3.结构体的内存对齐:4.结构体的位段:二、枚举是什么1.枚举的定义:2.枚举的使用:三、联合体是什么1.联合体的定义:2.联合体的特点:2.联合体的使用:2.联合体大小的计算:四、总结 前言 自定义类型包括结构体、枚举、联合体,这里教会你怎么使用! 一、结构体是什么 结构是一些值得集合,这些值统称为成员变量,结构的每个成员可以是不同类型的变量。 1.结构体的定义: struct tag{ memlist//成

森明帮大于黑虎帮的博客 4627

❤️C语言自定义类型的介绍❤️(结构体,枚举,联合体,位段)

这里写自定义目录标题???? 1.结构体????????1.1结构体概述????????????1.1.1结构体概念????????????1.1.2 结构体的声明与使用???????? 1.2结构体对齐及其大小计算????????????1.2.1偏移量????????????1.2.2结构体大小计算???????? 1.3结构体与位段????????????1.3.1位段????????????1.3.2位段实现结构体????2.枚举???????? 2.1枚举概述????????????2.1.1枚举

878

深入探索 C 语言中的自定义类型:结构体、联合体与枚举

结构体、联合体和枚举在 C 语言中各自扮演着重要角色。结构体擅长整合不同类型的数据,联合体能够有效节省内存,枚举则可以清晰地列举取值。而结构体实现的位段在特定场景下发挥着独特作用,尽管存在跨平台等问题,但合理使用能带来显著的性能提升。熟练掌握这些自定义类型及其特性,将使开发者在 C 语言编程的道路上如虎添翼,编写出更高效、更优质的代码。希望通过本文的介绍,大家能对它们有更深入的理解,并在实际编程中灵活运用。

2403_87794049的博客 892

一篇博客学会系列(2)—— C语言中的自定义类型 :结构体、位段、枚举、联合体

C语言的内置类型有:char、short、int、long、long long、float、double。而这些内置类型不能够解决所有问题,生活中会存在一些复杂对象。比如描述一个人,名字、性别、年龄、身高、体重.......描述一本书,书名、作者、出版社.......由于会存在复杂对象,因此C语言就支持了自定义类型,这就是这篇博客即将讲到的结构体、位段、枚举、联合体(共用体)。int x;int y;}p1;//声明类型的同时定义变量p1//定义结构体变量p2。

Hacynn的博客 715

第十三讲:自定义类型(结构体、联合体、枚举)

C语言结构体、联合体以及枚举详解。

yi_ren_yi_xin的博客 1184
上一篇: 指针笔试题详解(会了你就可以轻松玩转指针)
下一篇: 动态内存函数
理论灰色
博客等级 码龄5年 1536粉丝 92原创
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

理论灰色

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值