【自定义类型】(结构体、枚举、联合)

news2024/11/26 16:39:14

结构体内存对齐:

计算结构体的大小

结构体成员不是按照顺序在内存中连续存放的而是有一定的对齐规则的

结构体内存对齐的规则:

1、结构体的第一个成员永远放在相比于结构体变量起始位置的偏移量为0的位置。

2、从第二个成员开始,往后的每个成员都要对齐到某个对齐数的整数倍处。对齐数:结构体成员自身的大小和默认对齐数的较小值。在VS环境上的默认对齐数是8,在gcc(Linux)环境上没有默认对齐数,对齐数就是结构体成员的自身大小。

3、结构体的总大小必须是最大对齐数的整数倍(最大对齐数是所有成员的对齐数中的最大的值)

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


offsetof
对应的头文件是:#include <stddef.h>
可以计算结构体成员相较于结构体起始位置的偏移量

#include <stddef.h>
#include <stdio.h>

struct S1
{
	char c1;//1
	int i;//4
	char c2;//1
};
//0 - 1
//1 2 3 (4 5 6 7) - 4
//8 - 1
//0 - 8 - 9个空间单元 但是不是4的整数倍
//10 11 12是4的整数倍
//12

struct S2
{
	int i;//4
	char c1;//1
	char c2;//1
};
//0 1 2 3 - 4
//4 - 1
//5 - 1
//0 - 5 6个存储空间单元 但是不是4的整数倍
//7 8是4的整数倍
//8

int main()
{
	struct S1 s1 = { 0 };

	printf("%d\n", sizeof(struct S1));//12
	printf("%d\n", sizeof(struct S2));//8

	printf("%d\n", offsetof(struct S1, c1));//可以计算结构体成员相较于结构体起始位置的偏移量
	printf("%d\n", offsetof(struct S1, i));
	printf("%d\n", offsetof(struct S1, c2));

	printf("%d\n", offsetof(struct S2, i));
	printf("%d\n", offsetof(struct S2, c1));
	printf("%d\n", offsetof(struct S2, c2));
	return 0;
}

#include <stdio.h>

struct S3
{
	double d;
	char c;
	int i;
}; 
//0 - 7 - 8个
//8 - 1个
//9 10 11 (12 13 14 15) - 4个
//0 - 15 是16个空间刚好是8的整数倍
//16

struct S4
{
	char c1; // 1
	struct S3 s3; // 8 大小空间为16
	double d; // 8
};
//0 - 1个位置
//第二个是结构体:其对应的最大对齐数是8,移到8的位置开始
//这个结构体的总共大小为16,所以从8开始到23放这个结构体
//然后24开始到31存放第三个元素
//总共0-31是32个空间大小
//32 刚好32也是8的整数倍

int main()
{
	printf("%d\n", sizeof(struct S3));
	printf("%d\n", sizeof(double));//8
	printf("%d\n", sizeof(float));//4

	printf("%d\n", sizeof(struct S4));//32

	return 0;
}

在这里插入图片描述


如果说遇到数组作为结构体的元素:
int a[3];可以直接看作3个整型元素存放进去

总体来说:结构体的内存对齐是拿空间来换取时间


我们可以通过让占用空间小的成员尽量集中在一起

struct S1
{
	char c1;//1
	int i;//4
	char c2;//1
};//12

struct S2
{
	int i;//4
	char c1;//1
	char c2;//1
};//8

修改默认对齐数:
使用 #pragma

#pragma pack(8) //设置默认对齐数为8
#pragma pack()  //取消设置的默认对齐数,还原为默认
#pragma pack(1)
//默认对齐数为1
struct S
{
	char c1;//1 1 1
	int a; // 4 1 1
	char c2;//1 1 1
};

#pragma pack()

int main()
{
	printf("%d\n", sizeof(struct S));//6
	return 0;
}

位段
1、位段的成员必须是:int、unsigned int 或者 signed int(char也是属于整型家族的
2、位段的成员名后边有一个冒号和一个数字

struct A
{
	int _a : 2;//二进制位
	int _b : 5;
	int _c : 10;
	int _d : 30;
	//总共需要47个二进制位
	//1个int是32位
	//2个int是8个字节
};

int main()
{
	printf("%d\n", sizeof(struct A));//8

	return 0;
}
struct S
{
	char a : 3;
	//3个比特位 先给你一个字节
	char b : 4;
	//4个比特位
	char c : 5;
	//5个比特位 需要再去申请一个字节
	char d : 4;
	//4个比特位 需要再去申请一个字节
};
int main()
{
	struct S s = { 0 };
	s.a = 10;
	s.b = 12;
	s.c = 3;
	s.d = 4;
	printf("%d\n", sizeof(s));//3
	return 0;
}

枚举enum


联合(共用体)union

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

联合体大小的计算:联合体的大小至少是最大成员的大小

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

//判断大小端存储方式
int check_sys()
{
	union
	{
		int i;
		char c;
		//使用同一块空间
	}un = {.i = 1};
	return un.c;
	//01 00 00 00 小端
	//00 00 00 01 大端
}

int main()
{
	int ret = check_sys();
	

	if (ret == 1)
		printf("小端\n");//小端存储方式
	else
		printf("大端\n");

	return 0;
}
union Un1
{
	char c[5];//(5) 1 8 (1)
	int i;//(4) 8 (4)
};
//5 为了凑成4的整数倍 所以为8

union Un2
{
	short c[7];//(14) 2 8 (2)
	int i;//(4) 4 8 (4)
};
//14为了凑成4的整数倍 所以为16

int main()
{
	printf("%d\n", sizeof(union Un1));//5+3 = 8
	printf("%d\n", sizeof(union Un2));//16

	return 0;
}

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

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

相关文章

我打赌!这个 SQL 题,大部分人答不出来

周末的时候&#xff0c;一个读者问了我一个很有意思的问题&#xff0c;是关于 MySQL 中 update 加锁的问题。 他用下面这张数据库表&#xff0c;做了个 MySQL 实验的时候。 发现事务 B 的 update 不会阻塞&#xff0c;而事务 C 的 update 会阻塞&#xff0c;都是对 id 10 这条…

使用 uniswap 模拟交易时遇到一个问题

使用 uniswap 模拟交易时遇到一个问题 Error: VM Exception while processing transaction: socket hang upat web3.js:6365:9(39)at send (web3.js:5099:62(29))at <eval>:1:20(11)我的入参是 > eth.sendTransaction({from:0xe26a357fcc5A010421A49B8a5A99Af14CDe2…

Elasticsearch 中的矢量搜索:设计背后的基本原理

作者&#xff1a;Adrien Grand 你是否有兴趣了解 Elasticsearch 用于矢量搜索&#xff08;vector search&#xff09;的特性以及设计是什么样子&#xff1f; 一如既往&#xff0c;设计决策有利有弊。 本博客旨在详细介绍我们如何选择在 Elasticsearch 中构建矢量搜索。 矢量搜索…

科研 | 入门大全

文章目录 1. 读文献1.1 文献查阅与管理、如何快速找到与研究方向相关文章如何快速了解国内外发展现状找到后&#xff0c;怎么高效阅读&#xff1f;需要逐词逐句阅读吗&#xff1f;需要顺序阅读&#xff1f;读完之后&#xff0c;好像懂了&#xff0c;好像也没懂读过的文章&#…

通过GWO算法对8个发电机进行了最佳调度编码(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 通过GWO&#xff08;Grey Wolf Optimization&#xff09;算法对8个发电机进行最佳调度编码是一种优化问题的解决方法。GWO算法灵…

【C++】C++异常机制

文章目录 C异常C语言传统的错误处理方式C错误处理方式异常的使用方法异常的使用规范异常安全问题异常规范自定义异常体系STL中的异常体系异常的优缺点 C异常 C语言传统的错误处理方式 终止程序&#xff0c;如assert直接断言报错&#xff0c;缺陷&#xff1a;非常麻烦&#xff…

密码学总结杂七杂八的wp

快捷键 折叠&#xff08;展开&#xff09;所有代码这里是指按下快捷键后凡事.py文件里可折叠的都折叠。 折叠所有代码&#xff1a;Ctrl Shift - &#xff08;减号&#xff09; 展开所有代码&#xff1a;Ctrl Shift &#xff08;加号&#xff09; 折叠&#xff08;展开&…

Linux运维面试题(一)之网络基础类面试题

Linux运维面试题&#xff08;一&#xff09;之网络基础类面试题 1.简述ISO/OSI的七层模型的分层与作用2.TCP/IP 四层&#xff08;网络接口层&#xff09;/五层模型&#xff08;数据链路层物理层&#xff09;3.TCP协议与UDP协议工作在哪一层&#xff0c;作用是什么&#xff1f;4…

Java安全——JAAS

Java安全 从保护终端用户不受攻击的角度讨论&#xff1a; 默认沙箱可以保护终端用户不受恶意java程序的破坏数字签名可以保护终端用户数据的完整性加密则可以保护终端用户数据的机密性 如何防止终端用户的破坏的&#xff1f; 鉴别与授权&#xff08;Java Authentication and Au…

渗透专题丨Vulnhub-DC-1靶机打靶

打开靶机&#xff0c;使用nmap进行网段扫描&#xff1a; 排除主机和kali IP&#xff0c;锁定靶机IP&#xff1a;192.168.38.141&#xff1a; 接下来进行端口扫描&#xff1a; 扫描服务详细信息&#xff1a; 这里扫到内容管理系统&#xff0c;网站也扫出来了&#xff1a;http-ge…

每天高频算法题-DAY3

题目一 在一个 n * m 的二维数组中&#xff0c;每一行都按照从左到右 非递减 的顺序排序&#xff0c;每一列都按照从上到下 非递减 的顺序排序。请完成一个高效的函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该整数。 示例: 现有矩阵 ma…

电路分析 day01 一种使能控制电路

本次分析的电路为 一种使能控制电路 &#xff08;站在别人的肩膀上学习&#xff09; 资料来源 &#xff1a; 洛阳隆盛科技有限责任公司的专利 申请号&#xff1a;CN202022418360.7 1.首先查看资料了解本次电路 1.1 电路名称&#xff1a; 一种使能控制电路 1.2 电路功能…

Can转RTU网关can总线转以太网设备

YC-CAN-RTU 是一款用于 CAN-Modbus 现场总线与 RS-232 总线或 RS-485 总线之间数据转换的协议型转换器&#xff0c;支持标准 Modbus RTU 协议。集成 1 路RS-232 通道、1 路RS-485 通道、1 路CAN-Modbus 通道&#xff0c;可以方便地嵌入使用 RS-232 接口和 RS-485 接口的节点上&…

通过层级列表循环生成树结构

列表生成树结构 应用 前提: 列表有字段能表示所处层级(如Deep、Level).根据自己业务来。主要是针对列表对象来处理&#xff0c;组织成树结构。如下图&#xff1a; 在得到如图类似数据后&#xff0c;采取使用函数来组织树结构&#xff0c;同时生成层级序号&#xff08;1&…

TCP 与UDP区别

目录 网络参考模型TCPTCP 是什么特点 UDPUDP 是什么特点 TUP与UDP区别 总结什么时候选TCP or UDP 网络参考模型 TCP TCP 是什么 传输控制协议&#xff08;TCP&#xff09;是TCP/IP模型的传输层协议。它是一个面向连接的协议。因此&#xff0c;协议首先在源和目标之间建立连接…

《面试1v1》Redis内存优化

&#x1f345; 作者简介&#xff1a;王哥&#xff0c;CSDN2022博客总榜Top100&#x1f3c6;、博客专家&#x1f4aa; &#x1f345; 技术交流&#xff1a;定期更新Java硬核干货&#xff0c;不定期送书活动 &#x1f345; 王哥多年工作总结&#xff1a;Java学习路线总结&#xf…

WEB阶段_HTML(附代码笔记)

&#xff08;一&#xff09;案例一&#xff1a;网站信息页面的显示 1、HTML文档的创建 <html><head><title>01-HTML的文件创建&#xff08;浏览器标签显示的名字&#xff09;</title></head><body><h2>你好</h2></body>…

点云3D检测算法-Point pillar踩坑日记

工程地址&#xff1a; https://github.com/nutonomy/second.pytorch 1.环境搭建&#xff0c;跟着官网的教程走 1.1注意官网上的这条语句&#xff0c;存在一些坑 conda install pytorch torchvision -c pytorch 它会重新安装cudatoolkit和cudnn&#xff0c;版本可能很老旧&…

libtorch 调用模型方法

libtorch 是 pytorch 的 C 版本&#xff0c;支持 CPU 端和 GPU 端的模型部署。相较于用 tensorrt 部署 pytorch 模型&#xff0c;用 libtorch的优势在于&#xff1a;pytorch 和 libtorch 同属一个生态&#xff0c;API 语句比较接近&#xff0c;并且不会出现某网络层不支持的问题…

面试官:请求转发和请求重定向有什么区别?

在 Java 中&#xff0c;跳转的实现方式有两种&#xff1a;请求转发和请求重定向&#xff0c;但二者是完全不同的&#xff0c;所以我们今天就来盘它。请求转发和请求重定向主要区别&#xff0c;包含以下 5 点&#xff1a; 定义不同 跳转方不同 数据共享不同 最终 URL 地址不同…