C++ | 结构体及大小计算

news2024/11/24 2:39:17

C++结构体及大小计算


文章目录

  • C++结构体及大小计算
    • struct 和 class 区别
    • 字节对齐
      • 默认对齐方式
    • 位域
    • 使用#pragma pack(n)
    • 结构体中有结构体
    • Reference

struct 和 class 区别

结构体(struct)和类(class)有点像,均是定义一个数据单元,该数据单元中包含多个类型的数据,即成员变量,也可以包含多个方法。

创建结构体就像创建对象一样,一个对象有多个属性。

区别如下:

  • 结构体使用关键字 struct ,类使用关键字 class;
  • 通常情况下结构体声明只会声明成员变量,如果包含成员函数,就和类相似;
  • 结构体声明通常不包括 public 或 private 的访问修饰符;
  • 类成员默认情况是 private 的,而结构体的成员则默认为 public。

字节对齐

struct 的 sizeof 是所有成员字节对齐后长度相加,而 union 的 sizeof 是取最大的成员长度。

可以通过下面的方法来改变默认的对齐条件:

(1) 伪指令#pragma pack(n):C编译器将按照n个字节对齐。

(2) 伪指令#pragma pack():取消自定义字节对齐方式。

字节对齐的细节和编译器实现相关

一般而言,满足3个准则:

(1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除,即 最宽成员大小 首成员大小 = 整数 \frac{最宽成员大小}{首成员大小} = 整数 首成员大小最宽成员大小=整数

(2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是该成员大小的整数倍,即 偏移量 该成员大小 = 整数 \frac{偏移量}{该成员大小} = 整数 该成员大小偏移量=整数。如有需要编译器会在成员之间加上填充字节。

(3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节,即 结构体大小 最宽成员大小 = 整数 \frac{结构体大小}{最宽成员大小} = 整数 最宽成员大小结构体大小=整数

基本类型是指: char、short、int、float、double 等内置数据类型。

如果一个结构体中包含另外一个结构体成员,那么此时最宽基本类型成员取最宽的基本类型。

默认对齐方式

测试机器为64位ubuntu电脑

#include <iostream>

using namespace std;

typedef struct
{
	char randy1;  // 1个字节   / 1字节
	char randy2;  // 1个字节   / 2字节
	char randy3;  // 1个字节   / 3字节
}Q1;              // total size : 3

typedef struct
{
	int num;     // 4个字节
	char randy;  // 1个字节,补齐为8字节
}Q2;             // total size : 8

typedef struct
{
    char randy;  // 1个字节   / 1字节
	int num;     // 4个字节   / 5字节 -> 补齐3字节,共8字节
}Q2_1;             // total size : 8

typedef struct
{
	char randy;      // 1字节   / 1字节
	int sesame;      // 4字节   / 5字节 -> 补齐3字节,共8字节
	long long  qcj;  // 8字节   / 16字节
	char kim;        // 1字节   / 17字节 -> 补齐7字节,共24字节
}Q3;                 // total size : 24

typedef struct
{
	char randy;      // 1字节   / 1字节
    char kim;        // 1字节   / 2字节
	int sesame;      // 4字节   / 6字节 -> 补齐2字节,共8字节
	long long  qcj;  // 8字节   / 16字节
}Q3_1;               // total size : 16

typedef struct
{
	long sesame;     // 8字节 / 8字节
	char * pRandy;   // 8字节 / 16字节
	short int data;  // 2字节 / 18字节
	char randy;      // 1字节 / 19字节 -> 补齐5字节
}Q4;                 // total size : 24

int main(void)
{
    char randy;
    cout << "char: " << sizeof(randy) << endl;
    // 1

    char* pRandy;
    cout << "char *: " << sizeof(pRandy) << endl;
    // 8

    int sesame;
    cout << "int: " << sizeof(sesame) << endl;
    // 4

    short int shint;
    cout << "short int: " << sizeof(shint) << endl;
    // 2

    long qcj;
    cout << "long: " << sizeof(qcj) << endl;
    // 8


    long long qccccccccj;
    cout << "long long: " << sizeof(qccccccccj) << endl;
    // 8

	cout << "Q1: " << sizeof(Q1) << endl;      // Q1: 3
	cout << "Q2: " << sizeof(Q2) << endl;      // Q2: 8
    cout << "Q2_1: " << sizeof(Q2_1) << endl;  // Q2_1: 8
	cout << "Q3: " << sizeof(Q3) << endl;      // Q3: 24
    cout << "Q3_1: " << sizeof(Q3_1) << endl;  // Q3_1: 16
	cout << "Q4: " << sizeof(Q4) << endl;      // Q4: 24

	return 0;
}

位域

位域:指定某个成员变量所占用的二进制位数(Bit)

位域的宽度不能超过它所依附的数据类型的长度

如果指定了 char ch1:3,则ch1最多只能表示3个bit的char,最大不能超过8bit的char,其他基本类型依此类推。

#include <iostream>

using namespace std;

typedef struct
{
	char ch1:1; // 1+3+3=7位,所以只占1个字节
	char ch2:3;
	char ch3:3;
}Q1;              // total size : 1 Bytes

typedef struct
{
	char ch1 : 5; // 5+5+3=13位,所以只占2个字节
	char ch2 : 5;
	char ch3 : 3;
}Q2;              // total size : 2 Bytes

typedef struct
{
	char ch1 : 5; // 5+5+4=14bit,占3个字节
	char ch2 : 5;
	char ch3 : 4;
}Q3;              // total size : 3 Bytes

typedef struct
{
	char ch1 : 7; // 7+7=14位,却只占2个字节 【注意】
	char ch2 : 7;
}Q4;              // total size : 2 Bytes

typedef struct
{
	char ch1 : 1; // 偏移1个bit
	int a : 16;   // 偏移16个bit
	int b : 16;   // 偏移16个bit
}Q5;              // total size : 8 Bytes

typedef struct
{
	char ch1 : 1; 
	int a : 16;
	int b : 17;
}Q6;              // total size : 8 Bytes

int main(void)
{
	cout << "Q1: " << sizeof(Q1) << endl;  // Q1: 1
	cout << "Q2: " << sizeof(Q2) << endl;  // Q2: 2
	cout << "Q3: " << sizeof(Q3) << endl;  // Q3: 3
	cout << "Q4: " << sizeof(Q4) << endl;  // Q4: 2
	cout << "Q5: " << sizeof(Q5) << endl;  // Q5: 8
	cout << "Q6: " << sizeof(Q6) << endl;  // Q6: 8

	return 0;
}

使用#pragma pack(n)

#include <iostream>
using namespace std;

#pragma pack(1) // 要求补齐为“1”的倍数
typedef struct
{
	char randy; // 1 字节 / 1 字节,由于自定义了对齐方式,所以不再补齐
	int b;      // 4字节 / 5 字节
	int a;      // 4字节 / 9 字节
}Q1;            // total size : 9 Bytes

#pragma pack(2) // 要求补齐为“2”的倍数
typedef struct
{
	char randy; // 1+1 字节,由于自定义了对齐方式,补齐为"2"的倍数
	int b;      // 4字节 /6 字节
	int a;      // 4字节 /10 字节
}Q2;            // total size : 10 Bytes

#pragma pack(4) // 要求补齐为“2”的倍数
typedef struct
{
	char randy;    // 1+1 字节,由于自定义了对齐方式,补齐为"2"的倍数
	int b;         // 4字节 /6 字节
    short int a;   // 2字节 /8 字节
	int c;         // 4字节 /12 字节
}Q2_1;             // total size : 16 Bytes

#pragma pack(2)  // 要求补齐为“2”的倍数
typedef struct
{
	char randy; // 1 字节 / 2 字节 -> 补齐1字节,由于自定义了对齐方式,补齐为"2"的倍数
	int b;      // 4 字节 / 6 字节
	int a;      // 4 字节 / 10 字节
}Q3;            // total size : 10 Bytes

#pragma pack(4)  // 要求补齐为“4”的倍数
typedef struct
{
	char randy; // 1 字节 / 4 字节 -> 补齐3字节,由于自定义了对齐方式,补齐为"2"的倍数
	int b;      // 4 字节 / 8 字节
	int a;      // 4 字节 / 12 字节
}Q3_1;          // total size : 12 Bytes

#pragma pack(2)  // 要求补齐为“2”的倍数
typedef struct
{
	char randy;     // 1 字节 / 2 字节 -> 补齐1字节,由于自定义了对齐方式,补齐为"2"的倍数
	int b;          // 4 字节 / 6 字节
	short int c;    // 2 字节 / 8 字节
}Q3_2;              // total size : 8 Bytes

#pragma pack(4)
typedef struct
{
	long sesame;     // 8字节 / 8字节
	char * pRandy;   // 8字节 / 16字节
	short int data;  // 2字节 / 18字节
	char randy;      // 1字节 / 20字节 -> 补齐1字节
}Q4;                 // total size : 20

int main(void)
{
	cout << "Q1: " << sizeof(Q1) << endl;     // Q1: 9
	cout << "Q2: " << sizeof(Q2) << endl;     // Q2: 10
	cout << "Q2_1: " << sizeof(Q2_1) << endl; // Q2_1: 10
	cout << "Q3: " << sizeof(Q3) << endl;     // Q3: 10
	cout << "Q3_1: " << sizeof(Q3_1) << endl; // Q3_1: 12
	cout << "Q3_2: " << sizeof(Q3_2) << endl; // Q3_2: 8
    cout << "Q4: " << sizeof(Q4) << endl;     // Q4: 20
	return 0;
}

当 #pragma pack 的 n 值等于2的指数倍,如 $2^0, 2^1, 2^2, 2^3 $,若 n 超过所有数据成员长度的时候,这个 n 不产生任何效果。

结构体中有结构体

计算时仅需将内嵌的结构体展开即可

但是计算大小时,展开后的结构体的第一个成员的偏移量应当是被展开的结构体中宽度最大成员的整数倍,即 内嵌结构体最宽成员大小 首成员大小 = 整数 \frac{内嵌结构体最宽成员大小}{首成员大小} = 整数 首成员大小内嵌结构体最宽成员大小=整数

#include <iostream>

using namespace std;

typedef struct
{
	short c;    // 2 字节 / 2 字节
	char randy; // 1 字节 / 4 字节 -> 补齐1字节
	int sesame; // 4 字节 / 8 字节
	int kim;    // 4 字节 / 12 字节
}Q1;            // total size : 12 bytes

typedef struct
{
	short randy;     // 2字节 / 4 字节 -> 补齐2字节, 展开后的结构体的最大成员宽度为4

	struct
	{
		char randy; // 1 字节 / 8 字节 -> 补齐3字节 
		int jun;    // 4 字节 / 12字节
	}Q;

	int kim;        // 4 字节 / 16字节

}Q2;            // total size : 16 bytes

int main(void)
{
	cout << "Q1: " << sizeof(Q1) << endl; // Q1: 12
	cout << "Q2: " << sizeof(Q2) << endl; // Q2: 16

	return 0;
}

Reference

  • C++中的结构体所占内存空间总结

欢迎关注公众号【三戒纪元】

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

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

相关文章

Activi7工作流经典实战(附:常用流程流转代码片段)

一、Activiti7介绍 Activiti正是目前使用最为广泛的开源工作流引擎。Activiti的官网地址是 https:// www.activiti.org 历经6.x和5.x两个大的版本。 1. Activiti工作流引擎 他可以将业务系统中复杂的业务流程抽取出来&#xff0c;使用专门的建模语言BPMN2.0进行定义。业务流…

彻底搞清楚Handler,再也不怕面试官

Handler Handler可以说是Android框架里面很精髓的一部分了&#xff0c;面试必问&#xff0c;用的也最多 Handler是什么&#xff1f; 提到Handler大家一定不陌生&#xff0c;我们经常用它来切换线程&#xff0c;或者是说做一些延时任务等等。最常用的地方可能就是在网络请求中…

Flask全栈解决小问题系列(1)搭建一个bootstrap开发框架

时间不多,闲话少说,实践出真知! 1.目的:为实现FlaskBootStrap开发效果,搞个开发测试项目 2.搭建项目 1)建个test-bootstrap项目,项目目录结构如下: 2)appstart.py内容如下: import json from flask import Flask,redirect,render_templateapp Flask("__main__") …

00后太卷了上班还没3年,跳到我们公司起薪18k....

都说00后已经躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。前段时间我们部门就来了个00后&#xff0c;工作都还没三年&#xff0c;跳到我们公司起薪18K&#xff0c;都快接近我了。 后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。最近和他…

Yolov5/Yolov7改进:小目标到大目标一网打尽,轻骨干重Neck的轻量级目标检测器GiraffeDet

1.GiraffeDet介绍 论文:https://arxiv.org/abs/2202.04256 🏆🏆🏆🏆🏆🏆Yolov5/Yolov7魔术师🏆🏆🏆🏆🏆🏆 ✨✨✨魔改网络、复现前沿论文,组合优化创新 🚀🚀🚀小目标、遮挡物、难样本性能提升 🍉🍉🍉定期更新不同数据集涨点情况 本文是…

gitlab上传大文件限制问题解决

gitlab上传大文件限制问题解决 前景提要&#xff1a; 今天收到同事反馈遇到gitlab 上传大文件时候报如下错误 error: RPC failed; result22, HTTP code 413 fatal: The remote end hung up unexpectedly fatal: The remote end hung up unexpectedly从报错来看是因为文件大…

什么样的冷链保温箱,既环保又实用?

冷链物流运输已经应用在了很多行业中&#xff0c;作为冷链物流运输中的重要设备——冷链保温箱&#xff0c;起到了举足轻重的作用。如果选择不当&#xff0c;选到了劣质产品&#xff0c;尤其是化学行业或者食品行业&#xff0c;就有可能造成试剂失效或者是影响粮食食品安全问题…

2023英码科技激发团队活力,提升集体凝聚力团建拓展之旅圆满结束!

5月6日&#xff0c;时至立夏&#xff0c;风暖昼长&#xff0c;万物繁茂。 在这个生机盎然、活力四射的时节&#xff0c; 尤其适合出游&#xff0c;开展有益身心健康的活动。 这一天&#xff0c;英码科技全体家人们齐聚广州白云区钟落潭&#xff0c;开展一天好玩有趣又意义深…

SVN基本操作 使用教程

01-SVN概述 1、为什么需要SVN版本控制软件 2、解决之道 SCM&#xff1a;软件配置管理 所谓的软件配置管理实际就是对软件源代码进行控制与管理 CVS&#xff1a;元老级产品 VSS&#xff1a;入门级产品 ClearCase&#xff1a;IBM公司提供技术支持&#xff0c;中坚级产品 SVN&…

C++类与对象(三)

文章目录 一.初始化列表1.初始化列表的概念2.初始化列表的注意事项 二.explicit关键字1.单参数构造函数2.多参数构造函数 三.static成员1.static成员的概念2.static成员的特性 四.友元1.概念2.友元函数3.友元类 五.内部类1.概念2.内部类的性质 六.匿名对象七.拷贝对象时编译器的…

Docker安装MySQL主从配置

今天学习Docker安装MySQL主从配置 一、Master 1.1、拉取镜像 $docker pull mysql:8.0.25 1. 2、新建MySQL主服务器的容器实例&#xff0c;端口为3306 docker run -p 3306:3306 --name mysql-master \ -v /data/mysql/mysql-master/log:/var/log/mysql \ -v /data/mysql/mys…

WebSocket聊天功能小Demo

一、WebSocket简介 1.1 什么是WebSocket&#xff1f; WebSocket协议是基于TCP的一种网络协议&#xff0c;它实现了浏览器与服务器全双工&#xff08;Full-duplex&#xff09;通信。它允许服务端主动向客户端推送数据&#xff0c;这使得客户端和服务器之间的数据交换变得更加简…

模型微调的预处理

一.简历文本标注数据的准备 目标&#xff1a;把原始数据集转换为PaddleNLP支持的文本/文档抽取标注格式&#xff0c;为后续的模型微调做好准备。 工具&#xff1a;Label Studio 使用手册&#xff1a; applications/information_extraction/label_studio_text.md PaddlePad…

ai原创文章生成器-原创文章生成的软件

AI原创文章生成器——让你轻松批量生成高质量文章 随着内容创作的需求不断增加&#xff0c;人工撰写也难以满足快速高效的产出需求。在这种情况下&#xff0c;AI原创文章生成器应运而生&#xff0c;为人们创造了一种全新的自动化创作方式。下面我们就来了解一下这个神奇的工具…

无网络要求有网就能免费体验ChatGPT/GPT4

ChatGPT 是 OpenAI 公司开发的一款聊天机器人。它基于 OpenAI 的 GPT-3 语言模型,可以进行开域的自然语言聊天。主要特点如下: 开域聊天:ChatGPT可以聊任意话题,不需要预先定义话题范围或关键词,真正实现开放领域聊天。自然语言交互:ChatGPT可以理解并生成自然的语言表达,其对…

[答疑]事件和其影响的属性的对应是多样的

DDD领域驱动设计批评文集>> 《软件方法》强化自测题集>> 《软件方法》各章合集>> 第五元素 2023-5-2 19:16 这题是不是缺少条件啊&#xff1f;“按钮默认isEnabled为true&#xff0c;被点击后&#xff0c;isEnabled变为false” 是通过什么渠道达到S4状态…

视频截取gif方法分享,利用gif制作工具在线制作动图

表情包作为聊天社交中调节氛围的工具&#xff0c;而动态的gif表情包更是深受大众的喜爱。那么&#xff0c;这种gif动态图片要怎么制作呢&#xff1f;其实&#xff0c;很简单不需要下载软件&#xff0c;小白也能轻松操作的。 一、什么工具能够制作gif动画呢&#xff1f; 使用G…

freeswitch两个DTMF转换接口的区别

概述 freeswitch支持三种模式的DTMF传输方式&#xff0c;分别时inband、INFO、2833。 在传统的PSTN网络中&#xff0c;所有的DTMF码都是inband模式&#xff0c;所以VOIP网络和PSTN网络对接中&#xff0c;需要将DTMF码做格式转换&#xff0c;通常是2833和inband之间的转换。 …

普乐蛙数字文旅动感5d电影设备5d动感电影体验馆

普乐蛙5d动感影院7d互动影院设备&#xff0c;它是通过视觉、听觉、触觉、嗅觉和味觉&#xff0c;在特定的环境中模拟形成一种特定的空间&#xff0c;营造出身临其境的效果。普乐蛙5d动感影院7d互动影院设备&#xff0c;它是根据人体工程学设计的座椅&#xff0c;让观众坐在座椅…

【iOS】—— 实现WebSocket发送消息(SocketRocket第三方库的使用和解析)

文章目录 WebSocketWebSocket特点 SocketRocket导入头文件设置代理SRWebSocket的初始化和建立连接SRWebSocketDelegate 代理方法实现加上简单UI实现两个用户之间简单通信浅看了一点点源码&#xff08;理解的不深&#xff09; 偶然之间了解到了利用WebSocket实现后端和前端的相互…