计算结构体大小

news/2024/12/29 16:51:05/

计算结构体大小

目录

  • 计算结构体大小
    • 一. 结构体内存对齐
      • 1. 简介
      • 2. 嵌套结构体
    • 二. offsetof
    • 三. 内存对齐的意义
    • 四. 修改默认对齐数

一. 结构体内存对齐

以字节(bety)为单位

1. 简介

对于结构体成员在内存里的存储,存在结构体的对齐规则,并不是连续存放的。

例1:对下面程序,你认为结构体s的大小是多少呢?

#include <stdio.h>struct S1
{char a;int b;char c;
};int main()
{struct S1 s;printf("%d\n", sizeof(s));return 0;
}
  • 第一个成员存放的位置是该结构体偏移量为0的地址
    在这里插入图片描述

  • 其他成员变量需要根据偏移量存放在其对齐数的整数倍的位置处

vs 下:对齐数 = 编译器默认对齐数(值为8) 与 该成员变量大小的最小值

(Linux下: 对齐数 = 该成员变量的大小)

在这里插入图片描述


  • 结构体总大小是其每个成员对齐数中最大数值的整数倍
    在这里插入图片描述

2. 嵌套结构体

例2: 对下面代码中,结构体s的大小是?

#include <stdio.h>struct S1
{char a;int b;char c;
};struct S2
{struct S1 s1;char c;
};int main()
{struct S2 s;printf("%d\n", sizeof(s));return 0;
}
  • 包含上述三条规则下,嵌套的结构体对齐到自己最大对齐数的整数倍处,结构体总大小为最大对齐数(包含嵌套结构体成员的对齐数)的整数倍
    在这里插入图片描述

二. offsetof

在这里插入图片描述

  • 该宏可以用于计算结果体成员相对于起始位置的偏移量

示例:
在这里插入图片描述

  • 原码解析

    #define offsetof(s,m) ((size_t)&(((s*)0)->m))
    

将数字0(地址为0x00000000)强转为s*类型的数据,s是结构体,m是其成员,

通过&((s* )0->m)得到成员m处的地址,再转换为size_t类型数据(相当于得到m地址距离结构体起始地址0x00000000的偏移字节数)。


三. 内存对齐的意义

  1. 在不同平台下,不是所有硬件平台都可以取任意地址访问数据,某些平台只能在某些地址处取特点大小的数据。
  2. 此时对于内存对齐后的数据,处理器访问会更加便捷

示例:
在这里插入图片描述

结构体内存对齐为了用空间来换取时间

但是我们可以利用结构体内存对齐规则,更合理的设计成员变量位置,如:让占用空间小的成员放在一起。

四. 修改默认对齐数

在vs(Visual Studio)编译器下存在默认对齐数(8)

如果我们想要修改为其他数值,也是可以的。

使用预处理指令#pragma pack(数字),修改成你想要的结果

示例:
在这里插入图片描述

将默认对齐数调至2后,对于结构体s1:a在偏移量0的空间,b在偏移量2~5的空间,c在偏移量6的空间。从0 ~ 6一共7个字节的空间,不是最大对齐数2的整数倍,所有会再浪费1个字节空间,总大小为8个字节。

通常修改的默认对齐数都是2n2^n2n , n=(0,1,2...)n=(0,1,2...)n=(0,1,2...)

s1:a在偏移量0的空间,b在偏移量2~5的空间,c在偏移量6的空间。从0 ~ 6一共7个字节的空间,不是最大对齐数2的整数倍,所有会再浪费1个字节空间,总大小为8个字节。

通常修改的默认对齐数都是2n2^n2n , n=(0,1,2...)n=(0,1,2...)n=(0,1,2...)

🦀🦀观看~


http://www.ppmy.cn/news/28587.html

相关文章

用反射模拟IOC模拟getBean

IOC就是spring的核心思想之一&#xff1a;控制反转。这里不再赘述&#xff0c;看我的文章即可了解&#xff1a;spring基础思想IOC其次就是java的反射&#xff0c;反射机制是spring的重要实现核心&#xff0c;今天我看spring的三级缓存解决循坏引用的问题时&#xff0c;发现一个…

k8s node之间是如何通信的?

承接上文同一个node中pod之间如何通信&#xff1f;单一Pod上的容器是怎么共享网络命名空间的&#xff1f;每个node上的pod ip和cni0网桥ip和flannel ip都是在同一个网段10.1.71.x上。cni0网桥会把报文发送flannel这个网络设备上&#xff0c;flannel其实是node上的一个后台进程&…

【GeoDjango框架解析】配置geodjango开发环境

系列文章目录 【GeoDjango框架解析】配置geodjango开发环境 【GeoDjango框架解析】GDAL、GEOS、PORJ等配置的报错处理 文章目录系列文章目录前言一、安装postgresql数据库&#xff08;一&#xff09;Linux系统&#xff08;二&#xff09;windows系统二、安装postgis扩展三、安…

【代码训练营】day44 | 完全背包理论 518. 零钱兑换 II 377. 组合总和 Ⅳ

所用代码 java 完全背包 01背包物品只能使用一次 – 倒序遍历 for(i 0; i < weight.length; i){ 物品for (j bagWeight; j > weight[i]; j--){ 背包dp[j] max(dp[j], dp[j-weight[i]] value[i])} }完全背包物品可以使用无限次 – 正序遍历 for(i 0; i < weigh…

【玩转c++】git的安装和使用以及可视化处理

本期主题&#xff1a;git的安装和使用&#xff08;windows环境&#xff09;博客主页&#xff1a;小峰同学分享小编的在Linux中学习到的知识和遇到的问题 小编的能力有限&#xff0c;出现错误希望大家不吝赐1.两个工具介绍第一个工具git&#xff0c;链接gitee或者github等代码托…

亿级高并发电商项目-- 实战篇 --万达商城项目 十三(编写购物车、优化修改商品、下架商品方法、购物车模块监听修改商品、删除商品消息)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是小童&#xff0c;Java开发工程师&#xff0c;CSDN博客博主&#xff0c;Java领域新星创作者 &#x1f4d5;系列专栏&#xff1a;前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 &#x1f4…

前端学习---

1.简单且必须掌握的 1.MVVM是什么 将MVC中的V变为了MVVM&#xff0c;实现了双向绑定。其中VM就是vue的作用&#xff0c;这样页面的动态化可以通过vue来操作&#xff0c;而不是页面直接与后端操作&#xff0c;实现了前后端的分离 2.为什么vue采用异步渲染 &#xff1f; 调…

极智项目 | 实战pytorch arcface人脸识别

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多经验分享 大家好&#xff0c;我是极智视界&#xff0c;本文介绍 实战pytorch arcface人脸识别&#xff0c;并提供完整项目源码。 本文介绍的实战arcface人脸识别项目&#xff0c;提供完整的可以一键训练、测试的项目工程…