【海贼王编程冒险 - 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 -> 结构的基础知识

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

1.2 -> 结构的声明

例如描述一个学生:

struct Student
{
    char name[20]; //姓名
    int age; //年龄
    char id[20]; //学号
};

1.3 -> 特殊的声明

在声明结构时可以不完全声明

struct
{
    char name[20]; //姓名
    int age; //年龄
    char id[20]; //学号
}x;

1.4 -> 结构的自引用

typedef struct Node
{
    int data;
    struct Node* next;
}node;

1.5 -> 结构体变量的定义与初始化

struct Point
{
    int x;
    int y;
}p1; // 声明类型的同时定义变量p1

struct Point p2; // 定义结构体变量p2

// 初始化:定义变量的同时赋初值。
struct Point p3 = { 1, 2 };

struct Student  // 类型声明
{
    char name[20];  // 姓名
    int age;   // 年龄
};

struct Student stu = { "zzl", 21 }; // 初始化

struct Node
{
    int data;
    struct Point p;
    struct Node* next;
}n1 = { 1, {2,3}, NULL }; // 结构体嵌套初始化

struct Node n2 = { 2, {4, 5}, NULL }; // 结构体嵌套初始化

1.6 -> 结构体内存对齐

结构体的对齐规则:

->   第一个成员在与结构体变量偏移量为0的地址处。
->    其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 (VS中默认的值为8)
->    结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
->    如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

存在内存对齐的原因: 

->    平台原因(移植原因)
不是所有的硬件平台都能访问任意地址上的任意数据的;
某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
->    性能原因
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

总的来说:

 结构体的内存对齐是用空间换时间的做法。

设计结构体时,怎样满足内存对齐又节省空间?

让占用空间小的成员尽量集中在一起

struct Point
{
    char x;
    int y;
    char z;
}p1;

struct Point
{
    char x;
    char z;
    int y;
}p2;

 很显然,p1与p2类型虽然成员相同,但是占有的空间则是不同的。

1.7 -> 修改默认对齐数

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

#pragma pack(8) // 设置默认对齐数为8
struct Point1
{
    char x;
    int y;
    char z;
}p1;
#pragma pack() // 取消设置的默认对齐数,还原为默认对齐数

#pragma pack(2) // 设置默认对齐数为2
struct Point2
{
    char x;
    int y;
    char z;
}p2;
#pragma pack() // 取消设置的默认对齐数,还原为默认对齐数

int main()
{

    printf("p1占用空间字节数为: %d\n", sizeof(p1));
    printf("p2占用空间字节数为: %d\n", sizeof(p2));

    return 0;
}

运行结果:

 

1.8 -> 结构体传参

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

struct S
{
	int data[50];
	int num;
};
struct S s = { {1,2,3,4}, 21 };

// 结构体传参
void Print1(struct S s)
{
	printf("%d\n", s.num);
}

// 结构体地址传参
void Print2(struct S* ps)
{
	printf("%d\n", ps->num);
}
int main()
{

	Print1(s);  // 传结构体
	Print2(&s); // 传地址

	return 0;
}

很显然,Print2函数更好。

因为:

->  函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。
->  如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降

 结论:

结构体传参时,要传结构体的地址。

2 -> 位段

2.1 -> 什么是位段

位段的声明与结构相似,但是有两个不同:

->  位段的成员必须是 int、unsigned int 或signed int 。
->  位段的成员名后边有一个冒号和一个数字。

 例如:

struct S
{
	int _a : 3;
	int _b : 5;
	int _c : 7;
};

2.2 -> 位段的内存分配

  1. 位段的成员可以是 int, unsigned int, signed int 或者是 char (属于整形家族)类型。
  2. 位段的空间上按照需要以4个字节(int)或者1个字节(char)的方式开辟的。
  3. 位段涉及诸多不确定因素,位段是不跨平台的,注重可移植的程序应避免使用位段。

如:

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

struct S
{
	int _a : 3;
	int _b : 5;
	int _c : 7;
};

int main()
{

	struct S s = { 0 };
	s._a = 1;
	s._b = 2;
	s._c = 3;

	return 0;
}

2.3 -> 位段的跨平台问题

->  int 位段被当成有符号数还是无符号数是不确定的。
->  位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32),写成27,在16位机器会出问题。
->  位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
->  当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。

总结:

跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是存在跨平台问题。

2.4 -> 位段的应用

3 -> 枚举

3.1 -> 枚举类型的定义

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

定义的enum Day为枚举类型

{}内的内容是枚举类型的可能取值,称作枚举常量。 

3.2 -> 枚举的优点

优点:

  1. 增加代码的可读性与可维护性。
  2. 与#define定义的标识符相比,枚举有类型检查,更加的严谨。
  3. 防止命名污染(封装)。
  4. 便于调试。
  5. 使用方便,一次可以定义多个变量。

3.3 -> 枚举的使用

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

enum Day//星期
{
	Mon = 1,
	Tues = 2,
	Wed = 3,
	Thur = 4,
	Fri = 5,
	Sat = 6,
	Sun = 7
};

int main()
{

	enum Day day = Sat;
	
	return 0;
}

 4 -> 联合(共用体)

4.1 -> 联合类型的定义

联合是一种特殊的自定义类型。

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

// 联合类型的声明
union Un
{
	int a;
	char b;
};

union Un u; // 联合类型的定义

4.2 -> 联合的特点

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

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

// 联合类型的声明
union Un
{
	int a;
	char b;
};

union Un u; // 联合类型的定义

int main()
{

	printf("%d\n", &(u.a));
	printf("%d\n", &(u.b));
	
	return 0;
}

4.3 -> 联合大小的计算

  1. 联合的大小至少是最大成员的大小。
  2. 当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。
#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

union Un1
{
	int a;
	char b[10];
};

union Un2
{
	int a;
	short b[20];
};

int main()
{

	printf("%d\n", sizeof(union Un1));
	printf("%d\n", sizeof(union Un2));
	
	return 0;
}

运行结果:


感谢各位大佬支持!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/360433.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

山体滑坡在线安全监测预警系统(解决方案)

在近年来&#xff0c;随着全球气候变化的影响&#xff0c;山体滑坡等自然灾害频发&#xff0c;给人们的生命财产安全带来了严重威胁。为了有效预防和减少山体滑坡带来的危害&#xff0c;许多地方开始在山上安装山体滑坡在线安全监测预警系统&#xff08;解决方案&#xff09;。…

代码编写大模型

Code Llama 70B 提供与之前发布的 Code Llama 型号相同的三个版本&#xff1a; CodeLlama - 70B&#xff0c;基础代码模型&#xff1b;CodeLlama - 70B - Python&#xff0c;专门面向 Python 的 70B&#xff1b;Code Llama - 70B - Instruct 70B&#xff0c;它针对理解自然语言…

【gulp+jq+html】添加环境变量,并在js中使用(判断环境,更改api接口域名)+ 附gulpfile.js代码

参考博文&#xff1a; gulp分离环境 gulp中如何配置环境变量 gulp环境变量配置 1、安装cross-env插件 npm install cross-env -d2、package.json更改scripts "scripts": {"clean": "gulp clean","serve:test": "cross-env NODE…

503 Service Temporarily Unavailable nginx 原因和解决办法

前言 HTTP 503 Service Temporarily Unavailable 错误通常表示服务器无法处理请求&#xff0c;可能是由于服务器过载、维护或其他临时性问题导致的。在 Nginx 中&#xff0c;这种错误通常与后端服务的可用性问题相关。以下是可能的原因和解决办法&#xff1a; 正文…

UE4 CustomDepthMobile流程小记

原生UE opaque材质中获取CustomDepth/CustomStencil会报错 在其Compile中调用的函数中没有看到报错逻辑 材质节点的逻辑都没有什么问题&#xff0c;所以看一下报错 在HLSLMaterialTranslator::Translate中 修改之后 mobile流程的不透明材质可以直接获取SceneTexture::customd…

知识点积累系列(一)golang语言篇【持续更新】

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 知识点积累 系列文章的第一篇&#xff0c;记录golang语言相关的知识点 1.结构体的mapstructure是什么 mapstructure:"default" mapstructure是一个Go语言的库&#xff0c;用于将一个map中的值映射到…

“量子+半导体”!罗姆半导体与量子公司Quanmatic进行应用探索

​内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨慕一 编译/排版丨琳梦 卉可 深度好文&#xff1a;1500字丨10分钟阅读 2023年&#xff0c;日本半导体制造商Rohm&#xff08;罗姆&#xff09;与量子算法解决方案公司Quanmatic达成合作…

StarRocks -- 基础概念(数据模型及分区分桶)

1. 数据模型 StarRocks提供四种数据模型&#xff1a; Duplicate Key, Aggregate Key, Unique Key, Primary Key 1.1 Duplicate Key 适用场景&#xff1a; 分析原始数据&#xff0c;如原始日志和原始操作记录。可以使用多种方法查询数据&#xff0c;不受预聚合方法的限制。加…

【Linux】信号量

信号量 一、POSIX信号量1、信号量的原理2、信号量的概念&#xff08;1&#xff09;PV操作必须是原子操作&#xff08;2&#xff09;申请信号量失败被挂起等待 3、信号量函数4、销毁信号量5、等待信号量&#xff08;申请信号量&#xff09;6、发布信号量&#xff08;释放信号量&…

高校教学方法论简述

简述。 背景 高校教师的任务&#xff1a;教学、科研、服务、辅导等&#xff1b;高校教师通常缺乏课程与教学的专业基础&#xff1b;应用型高校的课程教学、科研不同于学术型高校&#xff1b;民办应用型高校教师如何安身立命&#xff1f;应用型高校的专业课程与教学特色 教完--…

02-opencv简单实例效果和基本介绍-上

机器视觉概述 机器视觉是人工智能正在快速发展的一个分支。简单说来,机器视觉就是用机器代替人眼来做测量和判断。机器视觉系统是通过机器视觉产品(即图像摄取装置,分CMOS和CCD两种)将被摄取目标转换成图像信号,传送给专用的图像处理系统,得到被摄目标的形态信息,根据像素…

Linux Archcraft结合内网穿透实现SSH远程连接

文章目录 1. 本地SSH连接测试2. Archcraft安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定SSH公网地址6. SSH固定地址连接7. 结语 Archcraft是一个基于Arch Linux的Linux发行版&#xff0c;它使用最简主义的窗口管理器而不是功能齐全的桌面环境来提供图形化用户界面。…

电加热热水器上架亚马逊美国站需要的UL174报告

电加热热水器上架亚马逊美国站需要的UL174报告 家用热水器出口美国需要办理UL174测试报告。 热水器就是指通过各种物理原理&#xff0c;在一定时间内使冷水温度升高变成热水的一种装置。分为制造冷气部分和制造热水部分。其实这两个部分又是紧密地联系在一起&#xff0c;密不可…

flask+django基于python的网上美食订餐系统_3lyq1

设计旨在提高顾客就餐效率、优化餐厅管理、提高订单准确性和客户的满意度。本系统采用 Python 语言作为开发语言&#xff0c;采用Django框架及其第三方库和第三方工具来进行开发。该方案分为管理员功能模块&#xff0c;商家功能模块以及用户前后功能模块三部分。开发前期根据用…

管理的四种风格

前言 管理的四种风格,一般的领导大概就是这几种管理模式,告知,辅导,参与,授权,还有就是乱搞式(神经病模式)。 一、告知式 告知式是指组织通过正式、明确的渠道,将信息传达给员工。这种方式通常用于传递基本的规章制度、工作流程、政策文件等。告知式的作用在于确保员…

SRC实战 | 信息泄露挖掘

本文由掌控安全学院 - 叴龙 投稿 1. 信息搜集 首先老语法先搜集一波&#xff0c;毕竟没有钓鱼和sg的能力&#xff0c;只能找注册站去挖挖了。 web.title”XX大学”&&web.body”忘记密码”&&web.body”注册” 2. 漏洞挖掘 这里找到一个可以注册网站接口&…

增量式PID和PWM输出控制比例阀开度

SMART PLC增量式PID算法公式和梯形图代码,请参考下面链接文章: https://rxxw-control.blog.csdn.net/article/details/125767636https://rxxw-control.blog.csdn.net/article/details/125767636PWM输出详细介绍 https://rxxw-control.blog.csdn.net/article/details/124083…

Linux下如何编译C/C++代码?从.c到.exe经历了什么?

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;强烈推荐优质专栏: &#x1f354;&#x1f35f;&#x1f32f;C的世界(持续更新中) &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;…

【深度学习每日小知识】Model Accuracy 模型准确率

Model Accuracy 模型准确率 模型准确性是衡量机器学习 (ML) 模型基于数据做出预测或决策的能力的指标。它是用于评估 ML 模型性能的常用指标&#xff0c;可用于比较不同模型的性能或评估特定模型对于给定任务的有效性。 有多种不同的方法来衡量模型的准确性&#xff0c;具体取…

C++入门学习(二十)与或非

逻辑运算符的符号表示&#xff1a; 与&#xff1a;&&或&#xff1a;||非&#xff1a;&#xff01; a && b如果a和b都为真&#xff0c;则结果为真&#xff0c;否则为假a || b如果a和b有一个为真&#xff0c;则结果为真&#xff0c;二者都为假时&#xff0c;结…