自定义类型(结构体、枚举、联合体)内存大小的计算方法

内存对齐

为什么会存在内存对齐?

大部分参考资料是这么说的:

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

总体来说,结构体的内存对齐是那空间换取时间的做法。

结构体

结构体的内存对齐规则

  • 结构体第一个成员放在偏移量为0的地址,其他成员要按照规则放在该成员对齐数的整数倍地址处,之后还需计算结构体总大小,就是结构体成员最大对齐数的整数倍。
  • 特殊情况:如果结构体中嵌套有结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍,结构体的整体大小是所有成员中最大对齐数的整数倍。

修改默认对齐数

结构在对齐方式不合适的时候,我么可以自己更改默认对齐数。

#pragma pack(8)    //设置默认对齐数为8
#pragma pack()     //取消设置的默认对齐数,还原为默认
#pragma pack(1)    //设置默认对齐数为1

位段

struct A
{
    int _a:2;
    int _b:5;
    int _c:10;
    int _d:30;
};
printf("%d\n", sizeof(struct A));

位段的内存计算

以上段代码为例:

  • 冒号后面的数字表示该成员为n位,结构体向最长的int对齐,前三个加起来为17位,超过2个字节,不到4个字节,但加上第四个成员30位,就超过4个字节,所以第四个成员需要对齐到4字节处,前三个成员合起来占4个字节,第四个成员占4个字节,共8个字节。
  • 结构体最大对齐数为4,8是4的整数倍,所以整个结构体的大小为8.

枚举

枚举==列举

比如:

  • 一周的星期一到星期日是有限的7天,可以一一列举。
  • 性别有:男、女、保密,也可以一一列举。
  • 月份有12个月,也可以一一列举
  • 颜色也可以一一列举。

我们可以使用 #define 定义常量,为什么非要使用枚举?

枚举的优点

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

枚举的内存计算

enum Day//星期
{
    Mon,
    Tues,
    Wed,
    Thur,
    Fri,
    Sat,
    Sun
};
enum Sex//性别
{
    MALE,
    FEMALE,
    SECRET
};
enum Color//颜色
{
    RED=1,
    GREEN=2,
    BLUE=4,
    YELLOW
}

上面的 Day 、Sex 、Color 都是枚举类型,{ }内容都是枚举类型的可能取值,也就是枚举常量。
这些可能取值都是有值的,默认从0开始,一次递增1。也可以在定义的时候赋初始值,

比如上面Sex里的MALE为0,FEMALE为1,SECRET为2.
Color里的RED为1,GREEN为2,BLUE为4,YELLOW为5

联合(共用体)

联合的特点

  1. 成员共用同一块内存空间
  2. 联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。
  3. 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

联合的内存计算

union Un
{
    int i;
    char c;
};
union Un un;

例中联合变量un的大小就是最大成员的大小4
特例:

union Un1
{
    char c[5];    //1*5=5
    int i;
};
//最大对齐数4,对齐之后:8
union Un2
{
    short c[7];   //2*7=14
    int i;
};
//最大对齐数4,对齐之后:16
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));


如上例这样,最大成员不是最大对齐数的整数倍,就要对齐到最大对齐数的整数倍。

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

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

相关文章

LeetCode---386周赛

题目列表 3046. 分割数组 3047. 求交集区域内的最大正方形面积 3048. 标记所有下标的最早秒数 I 3049. 标记所有下标的最早秒数 II 一、分割数组 这题简单的思维题,要想将数组分为两个数组,且分出的两个数组中数字不会重复,很显然一个数…

Apache Flink连载(三十七):Flink基于Kubernetes部署(7)-Kubernetes 集群搭建-2

🏡 个人主页:IT贫道-CSDN博客 🚩 私聊博主:私聊博主加WX好友,获取更多资料哦~ 🔔 博主个人B栈地址:豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录

BUGKU 网站被黑

打开环境,什么都没发现,使用蚁剑扫描一下,发现shell.php,打开 使用BP抓包,进行爆破 得到密码:hack 进去得到flag

Vins-Moon配准运行

Vins-Moon运行 源码地址电脑配置环境配置编译适配Kitti数据集运行结果Euroc数据集kitti数据集 evo评估(KITTI数据)输出轨迹(tum格式)结果 源码地址 源码链接:https://github.com/HKUST-Aerial-Robotics/VINS-Mono.git 电脑配置 Ubuntu 18.…

2024年不容错过的行业峰会盛宴,引领未来商业潮流!

随着全球经济的不断演变和科技的日新月异,行业峰会成为了企业领袖、创新者和投资者们洞察未来趋势、交流前沿思想的重要平台。 2024年,一系列引人瞩目的行业峰会即将拉开帷幕,它们将汇聚全球精英,共同探讨各行业的未来发展之路。…

ssm637教材管理系统

** 🍅点赞收藏关注 → 私信领取本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅** 一 、设计说明 1.1研究背…

day02-JavaScript-Vue

文章目录 1 JavaScript1.1 介绍 1.2 引入方式1.3 基础语法1.3.1 书写语法1.3.2 变量1.3.3 数据类型和运算符 1.4 函数1.4.1 第一种定义格式1.4.2 第二种定义格式 1.5 JavaScript对象1.5.1 基本对象1.5.1.1 Array对象语法格式特点属性和方法 1.5.1.2 String对象语法格式属性和方…

unity学习(45)——选择角色菜单——客户端处理服务器的数据

1.已知客户端ReceiveCallBack中已经收到来自服务器返回的数据包。 2.问题是客户端MessageManager中的Update并没有拆解该数据包 ,因该是因为脚本没有挂载。 挂在SelectMenu场景中的Camera上即可。 挂载后成功达到目地 其中Update中的List是一个起到全局效果的static…

[GYCTF2020]EasyThinking --不会编程的崽

看标题就知道,这大概率是关于thinkphp的题目。先尝试错误目录使其报错查看版本号 thinkphp v6.0.0,在网上搜索一下,这个版本有一个任意文件上传漏洞。参考以下文章。 https://blog.csdn.net/god_zzZ/article/details/104275241 先注册一个账…

【python】遵守 robots.txt 规则的数据爬虫程序

程序1 编写一个遵守 robots.txt 规则的数据爬虫程序涉及到多个步骤,包括请求网页、解析 robots.txt 文件、扫描网页内容、存储数据以及处理异常。由于编程语言众多,且每种语言编写爬虫程序的方式可能有所不同,以下将使用 Python 语言举例&am…

javascript中对包含关系判断介绍

本文将为您详细讲解 JavaScript 中对包含关系的判断,包括数组、字符串等,并提供相应的代码例子。 1. 数组包含关系判断 在 JavaScript 中,数组包含关系判断通常使用 Array.prototype.includes() 方法。这个方法返回一个布尔值,表示…

手撕经典数据结构——堆

堆的函数主要有,插入,删除,查看堆顶元素。 建堆主要依靠插入函数。 我们需要定义一个数组,int类型长度和int类型容量。 在操作过程中我们需要用到查看父亲节点函数,查看左孩子节点函数,查看右孩子节点函数和…

[GXYCTF2019]BabyUpload1 -- 题目分析与详解

目录 一、题目分析 1、判断题目类型: 2、上传不同类型的文件进行测试: 二、题目详解 1、写出.htaccess文件: 2、.htaccess 文件配合 .jpg 上传: 3、利用 中国蚁剑/中国菜刀 获取flag: 一、题目分析 1、判断题目…

2024.03.01作业

1. 基于UDP的TFTP文件传输 #include "test.h"#define SER_IP "192.168.1.104" #define SER_PORT 69 #define IP "192.168.191.128" #define PORT 9999enum mode {TFTP_READ 1,TFTP_WRITE 2,TFTP_DATA 3,TFTP_ACK 4,TFTP_ERR 5 };void get_…

内存空间担保机制

什么是内存空间担保机制? 内存空间担保机制(Memory Space Guarantee)是垃圾回收(Garbage Collection)算法中的一种策略。它用于在进行垃圾回收过程(如Minor GC或Full GC)时,确保老年…

KubeSphere平台安装系列之三【Linux多节点部署KubeSphere】(3/3)

**《KubeSphere平台安装系列》** 【Kubernetes上安装KubeSphere(亲测–实操完整版)】(1/3) 【Linux单节点部署KubeSphere】(2/3) 【Linux多节点部署KubeSphere】(3/3) **《KubeS…

【IC前端虚拟项目】inst_buffer子模块DS与RTL编码

【IC前端虚拟项目】数据搬运指令处理模块前端实现虚拟项目说明-CSDN博客 需要说明一下的是,在我所提供的文档体系里,并没有模块的DS文档哈,因为实际项目里我也不怎么写DS毕竟不是每个公司都和HISI一样对文档要求这么严格的。不过作为一个培训的虚拟项目,还是建议在时间充裕…

C++ //练习 10.22 重写统计长度小于等于6 的单词数量的程序,使用函数代替lambda。

C Primer(第5版) 练习 10.22 练习 10.22 重写统计长度小于等于6 的单词数量的程序,使用函数代替lambda。 环境:Linux Ubuntu(云服务器) 工具:vim 代码块 /********************************…

RNA-Seq 笔记 [4]

***********************该笔记为初学者笔记,仅供个人参考谨慎搬运代码****************************** samtools 排序压缩和 featureCounts 生成基因计数表 SAM文件和BAM文件 1.SAM格式:是一种通用的比对格式,用来存储reads到参考序列的比…

二维数组详解(C语言)

一维数组详解链接:http://t.csdnimg.cn/PbzKF 前言看过一维数组,我们来看一下二维数组。 目录 目录 1. ⼆维数组的创建 1.1 ⼆维数组的概念 1.2 ⼆维数组的创建 2. ⼆维数组的初始化 2.1 不完全初始化 2.2 完全初始化 2.3 按照⾏初始化 2.4 初…