【C语言】结构体、位段、枚举、联合(共用体)

结构体

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

结构体声明:struct是结构体关键字,结构体声明不能省略struct;

匿名结构体:只能在声明结构体的时候声明结构体成员,之后再想用这个结构体声明结构体成员时就不行了;因为匿名结构体只能用一次,没有结构体名字没有办法声明结构体成员;(只打算用一次的结构体)


 结构体变量的声明与初始化

结构体变量的初始化需要使用大括号进行初始化;

// 结构体成员的声明与初始化
struct student 
{ // 声明的是一个描写学生的结构体char name[20];int age;char sex[5];
} s1 = { "张三", 18, "男" }; // 声明的是结构体成员并初始化;
int main()
{struct student s2 = { "李四", 19, "女" }; // 声明的是结构体成员并初始化;struct student s3 = { .age = 20, .name = "王五", .sex = "男" }; // 指定初始化结构体成员变量,通过 . 指定;// 如果不指定初始化结构体成员变量,就顺序初始化;printf("%s %d %s\n", s1.name, s1.age, s1.sex);printf("%s %d %s\n", s2.name, s2.age, s2.sex);printf("%s %d %s\n", s3.name, s3.age, s3.sex);return 0;
}

 结构的自引用

可以包含同类型的结构体指针,但是不能包含同类型结构体;

#include <stdio.h>
struct Node
{int data; // 存储数据 -> 数据域struct Node* n; // 存放下一个节点的地址 -> 指针域// 可以包含同类型结构体指针,但是不能包含同类型结构体
};

结构体内存对齐

怎么对齐:

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

2、其他成员变量要对齐到对齐数的整数倍的地址处;

3、对齐数:VS默认对齐数、结构体成员自身大小就是对齐数,取较小的对齐数

4、结构体总大小为最大对齐数的整数倍(每个成员都有一个对齐数),所有成员中的最大对齐数

5、嵌套结构体的对齐,嵌套的结构体要对齐到自身最大对齐数的整数位;结构体的大小就是所有成员中的最大对齐数的整数倍

为什么对齐:

1、不是所有硬件平台都能访问任意地址上的数据的,有些只能在特定位置处取某些特定数据;

2、结构体(尤其是栈)应该尽可能在自然边界上对齐;未对齐的内存,处理器需要访问两次;而对齐的只需访问一次;

3、结构体的内存对齐就是拿空间换取时间的;

如何节省空间:让占用空间小的成员集中在一起;

代码验证: 
#include <stdio.h>
int main()
{struct S{char c1;int a;double b;char c2;}s;struct S1{int a;char c1;char c2;double b;}s1;printf("%d\n", sizeof(s));printf("%d\n", sizeof(s1));return 0;
}

百度笔试题: 

 写一个宏,计算结构体中某变量相对于首地址的偏移(offsetof宏);

 offsetof宏的使用:
#include <stdio.h>
#include <stddef.h>
int main()
{struct S{char c1;int a;double b;char c2;}s;struct S1{int a;char c1;char c2;double b;}s1;// offsetof宏:结构体成员变量相对于首地址的偏移量printf("%d %d %d %d\n", offsetof(struct S, c1), offsetof(struct S, a), offsetof(struct S, b), offsetof(struct S, c2));printf("%d %d %d %d\n", offsetof(struct S1, a), offsetof(struct S1, c1), offsetof(struct S1, c2), offsetof(struct S1, b));printf("%d\n", sizeof(s));printf("%d\n", sizeof(s1));return 0;
}

结构体传参:

1、传值调用,形参相当于一份临时拷贝,修改形参不会改变实参;

2、传址调用,如果不加上const,修改新参就会改变实参;

3、传址调用比传值调用更节省空间,结构体传参尽量传址;


位段

1、设计位段的目的就是为了节省空间;

2、位段的成员必须是int、unsigned int、signed int(c99之后,其他类型也可以,但是基本都是int、char类型);

3、位段的成员名后边有一个冒号和一个数字(数字表示几个比特位);

4、位段:为表示二进制位;

#include <stdio.h>
int main()
{struct S1 // 结构体{int a;int b;char c;};struct S2 // 位段{int a : 2;int b : 4;char c : 1;};printf("%d\n", sizeof(struct S1));printf("%d\n", sizeof(struct S2));return 0;
}

 位段的内存分配

1、不知道是从低位开始分配还是从高位才是分配,这是不确定的;


 位段的跨平台问题:

1、int位段被当成有符号数还是无符号数是不确定的;

2、位段中最大位的值是不确定的;

3、位段中的成员在内存中,从右到左还是从左到右分配标准未定义;

4、一个结构包含两个位段,第二个位段无法容纳于第一个位段剩余的位时,是舍弃位还是利用,是不确定的;


枚举

枚举类型的定义:

1、把可能的取值一一列举(月份、星期);

2、必须包含关键字enum;

3、枚举的值是默认从0一次递增的;

4、枚举常量的默认值是可以修改的;

#include <stdio.h>
enum Color
{RED, // 注意,这是逗号,不是分号GREEN,BLUE  // 最后这里什么符号都没有
};
enum Sex
{MALE = 2, // 枚举常量的默认值是可以修改的FEMALE = 4,CECRECY = 1
};
int main()
{printf("%d\n", RED);printf("%d\n", GREEN);printf("%d\n", BLUE); // 打印枚举常量printf("%d\n", FEMALE);return 0;
}

 枚举的优点:

1、枚举可以增加代码的可读性和可维护性;

2、#define是用于替换的,没有类型的,但枚举有类型检查;

3、可以一次定义多个常量;


联合(共用体)

1、联合定义的变量包含一系列的成员;

2、这些成员共用同一块空间,所以也叫做共用体;

3、在同一时间段内,联合体内的成员不能同时使用,只能使用其中一个;

4、如果修改联合体内其中一个成员的值,则另一个的值也会改变;

5、联合体的关键字:union;

#include <stdio.h>
union Un
{int a;char b;
};
int main()
{union Un un;un.a = 10;un.b = 'a'; printf("%d\n", sizeof(un)); // 大小是成员中较大的那个大小printf("%p\n", &un);printf("%p\n", &(un.a));printf("%p\n", &(un.b)); // 说明联合体共用一块空间return 0;
}

 联合体大小的计算

1、联合体的大小是最大成员的大小,这句话是错的;

2、联合体的大小至少是最大成员的大小;

3、当最大成员大小没有对齐到最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍处;

#include <stdio.h>
union Un
{short a[7]; // 对齐数 2int b; // 对齐数 4// a占14个字节// 但是不是最大对齐数的整数倍// 所以联合体的大小是16
}un;
int main()
{printf("%d\n", sizeof(un));return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在pycharm中运行js文件,附加node.js下载步骤

文章目录 一、前言二、node.js安装和配置(如果之前就安装好了可以直接跳过)1、进入官网下载安装包2、在本地安装node.js3、环境配置4、验证是否安装成功5、修改下载位置(默认是在c盘&#xff0c;这个根据个人需求)6、设置默认模块包7、测试一下是否修改成功(要进入管理员模式的…

11 | JpaRepository 如何自定义

EntityManager 介绍 Java Persistence API 规定&#xff0c;操作数据库实体必须要通过 EntityManager 进行&#xff0c;而我们前面看到了所有的 Repository 在 JPA 里面的实现类是 SimpleJpaRepository&#xff0c;它在真正操作实体的时候都是调用 EntityManager 里面的方法。…

云上攻防-云原生篇K8s安全Config泄漏Etcd存储Dashboard鉴权Proxy暴露

文章目录 云原生-K8s安全-etcd未授权访问云原生-K8s安全-Dashboard未授权访问云原生-K8s安全-Configfile鉴权文件泄漏云原生-K8s安全-Kubectl Proxy不安全配置 云原生-K8s安全-etcd未授权访问 攻击2379端口&#xff1a;默认通过证书认证&#xff0c;主要存放节点的数据&#x…

升级包版本之后Reflections反射包在springboot jar环境下扫描不到class排查过程记录

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

卡顿分析与布局优化

卡顿分析与布局优化 大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能。Android系统每隔大概16.6ms发出VSYNC信 号&#xff0c;触发对UI进行渲染&#xff0c;如果每次渲染都成功&#xff0c;这样就能够达到流畅的画面所需要的60fps&#xff0c;为了能够实现60fp…

LabVIEW生产者消费者架构

LabVIEW生产者消费者架构 生产者/消费者模式可以轻松地同时处理多个进程&#xff0c;同时还能以不同速率迭代。 缓冲通信 当多个进程以不同速度运行时&#xff0c;就适合采用进程间缓冲通信。有了足够大的缓冲区后&#xff0c;生产者循环可以以快于消费者循环的速度运行&…

c语言练习89:链表的使用

链表的使用 虽然有这么多的链表的结构&#xff0c;但是我们实际中最常⽤还是两种结构&#xff1a; 单链表 和 双向带头循环链表 1. ⽆头单向⾮循环链表&#xff1a;结构简单&#xff0c;⼀般不会单独⽤来存数据。实际中更多是作为其他数据结 构的⼦结构&#xff0c;如哈希桶、…

在vs code中创建一个名为 “django_env“ 的虚拟环境报错?!以下方法可以解决

# vs code 终端窗口中运行&#xff1a; mkvirtualenv django_env # 拓展&#xff1a; mkvirtualenv django_env 是一个命令&#xff0c;用于创建一个名为 "django_env" 的虚拟环境。虚拟环境是一种用于隔离不同Python项目所需依赖的工具。通过创建虚拟环境&#x…

word 如何编写4x4矩阵

百度上给的教程&#xff0c;打印出来没有对齐 https://jingyan.baidu.com/article/6b182309995f8dba58e159fc.html 百度上的方式试了一下&#xff0c;不会对齐。导致公式看起来很奇怪。 下面方式会自动对齐 摸索了一下发现可以用下面这种方式编写 4x4 矩阵。先创建一个 3x3…

基于Linux上MySQL8.*版本的安装-参考官网

本地hadoop环境安装好,并安装好mysql mysql下载地址及选择包 MySQL :: Download MyS的QL Community Server (Archived Versions) mysql安装步骤 下载与上传解压给权限 #mysql安装包上传到/opt下 cd /usr/local/ #解压到此目录 tar -xvf /opt/mysql-8.0.33-linux-glibc2.12-…

[Machine Learning][Part 5]监督学习——逻辑回归

之前文章中提到监督学习的应用可分为两类&#xff1a;线性回归和逻辑回归。和线性回归不同&#xff0c;逻辑回归输出只有0和1。对于一个逻辑回归任务&#xff0c;可以先使用线性回归来预测y。然而我们希望逻辑回归预测模型输出的是0和1&#xff0c;为了达到这个目的&#xff0c…

Ubuntu:VS Code IDE安装ESP-IDF【保姆级】

物联网开发学习笔记——目录索引 参考&#xff1a; VS Code官网&#xff1a;Visual Studio Code - Code Editing. Redefined 乐鑫官网&#xff1a;ESP-IDF 编程指南 - ESP32 VSCode ESP-ID Extension Install 一、前提条件 Visual Studio Code IDE安装ESP-IDF扩展&…

微信小程序 uniapp+vue线上洗衣店业务管理系统演89iu2

本课题意在设计一种系统的、基于用户体验的线上洗衣服务模式&#xff0c;具有如下的研究意义: (1)为用户提供更简单、便捷的洗衣服务模式; (2)为智能柜的盈利模式提供了新的方向; (3)通过线上系统、智能柜与洗衣工厂结合的方式&#xff0c;为洗衣企业构建了一套节 省人力成本的…

使用VS Code终端窗口创建Python虚拟环境

在日常的Python开发中&#xff0c;管理项目的依赖关系是至关重要的。一个非常有用的工具是Python虚拟环境&#xff0c;它允许我们可以在同一计算机上隔离不同项目的依赖&#xff0c;以确保它们不会相互干扰。在本文中&#xff0c;我们将介绍如何在VS Code终端窗口中使用命令mkv…

论文阅读:CenterFormer: Center-based Transformer for 3D Object Detection

目录 概要 Motivation 整体架构流程 技术细节 Multi-scale Center Proposal Network Multi-scale Center Transformer Decoder Multi-frame CenterFormer 小结 论文地址&#xff1a;[2209.05588] CenterFormer: Center-based Transformer for 3D Object Detection (arx…

WSL Ubuntu 22.04.2 LTS 安装paddle踩坑日记

使用conda安装paddlepaddle-gpu: conda install paddlepaddle-gpu2.5.1 cudatoolkit11.7 -c https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/Paddle/ -c conda-forge 等待安装... 报错处理&#xff1a; (1)(1)PreconditionNotMetError: Cannot load cudnn shared libr…

205、使用消息队列实现 RPC(远程过程调用)模型的 服务器端 和 客户端

目录 ★ RPC模型&#xff08;远程过程调用通信模型&#xff09;▲ 完整过程&#xff1a;代码演示总体流程解释&#xff1a;ConstantUtil 常量工具类ConnectionUtil RabbitMQ连接工具类Server 服务端Client 客户端测试结果服务端客户端 完整代码ConstantUtil 常量工具类Connecti…

AMD AFMF不但能用在游戏,也适用于视频

近期AMD发布了AMD Software Adrenalin Edition预览版驱动程序&#xff0c;增加了对平滑移动帧&#xff08;AMD Fluid Motion Frames&#xff0c;AFMF&#xff09;功能的支持&#xff0c;也就是AMD的“帧生成”技术&#xff0c;与DLSS 3类似&#xff0c;作为FidelityFX Super Re…

137. 只出现一次的数字 II

题目 题解 方法一 直接用 哈希表出现 3 次则从 哈希表移除&#xff0c;最后剩下的就是结果 class Solution { public int singleNumber(int[] nums) { Map<Integer, Integer> map new HashMap<>(); for (int num : nums) { Integer i…

React添加文件路径时使用@符号代替src目录(非creae-react-app)

在其它项目中看到的可以用符号来代替src目录&#xff0c;那么在自己的react项目中也必须得尝试一下。本人的项目不是通过create-react-app脚手架来创建的&#xff0c;无法使用craco或者的方案来实现。 jsconfig.json配置 用的vscode进行开发&#xff0c;查看项目当中是否存在js…