当前位置: 首页 > news >正文

C语言的结构体在内存中是如何存放的?

目录

      • 1. 顺序存储:
      • 2. 对齐(Alignment):
      • 3. 填充(Padding):
      • 4. 结构体整体对齐:
      • 5. 强制对齐:
      • 示例:

C语言中的结构体在内存中的存储方式由以下几个关键概念决定:

1. 顺序存储:

结构体的成员变量按照它们在定义中出现的顺序存储在内存中。假设我们有以下结构体:

typedef struct {char a;int b;char c;
} MyStruct;

在这种情况下,成员变量在内存中的存放顺序为:abc

2. 对齐(Alignment):

为了提高访问速度,现代计算机体系结构通常要求特定类型的数据在特定的边界上对齐。对齐规则的具体实现依赖于系统架构和编译器设置,但常见的规则如下:

  • char 类型通常在 1 字节边界对齐。
  • int 类型通常在 4 字节边界对齐。
  • double 类型通常在 8 字节边界对齐。

3. 填充(Padding):

由于对齐规则的存在,结构体中可能会出现“空隙”或者“填充”字节,以确保每个成员变量都对齐到正确的边界上。这些填充字节不可避免地会增加结构体的总大小。

举个例子:

typedef struct {char a;   // 1 byteint b;    // 4 bytes (通常情况下)char c;   // 1 byte
} MyStruct;

在上面的例子中,char a 之后是 int b,而 int 需要 4 字节对齐。因为 char a 只占用 1 个字节,所以在 int b 之前会有 3 个字节的填充,使得 b 在 4 字节边界对齐。接下来,char c 不需要额外的填充。总大小为 8 字节(1+3+4+1)。

4. 结构体整体对齐:

结构体的总大小也会根据其最大成员的对齐需求进行对齐。以确保数组的每个元素都能按照最大成员的对齐方式对齐。

例如,如果我们有以下结构体:

typedef struct {char a;   // 1 byteint b;    // 4 bytesdouble c; // 8 bytes
} MyStruct2;

假设 char 对齐为 1 字节,int 对齐为 4 字节,double 对齐为 8 字节。成员变量的内存布局如下:

  • a:1 字节(偏移量 0)
  • 填充:3 字节(使 b 对齐到 4 字节边界)
  • b:4 字节(偏移量 4)
  • c:8 字节(偏移量 8,无需填充)

总大小为 16 字节,MyStruct2 的每个实例都会对齐到 8 字节边界,因为 c 是最大成员,其对齐需求为 8 字节。

5. 强制对齐:

在某些情况下,可以使用编译器指令或编译器特定的关键词(如 #pragma pack__attribute__((packed)))来更改结构体的默认对齐方式,减少填充字节,但这样做可能会降低访问速度。

示例:

以下示例代码展示了结构体在内存中的分布和大小计算:

#include <stdio.h>typedef struct {char a;   // 1 byteint b;    // 4 byteschar c;   // 1 byte
} MyStruct;int main() {printf("Size of MyStruct: %zu\n", sizeof(MyStruct));return 0;
}

输出结果:

Size of MyStruct: 12

这表明,编译器为 bc 之间以及结构体末尾添加了填充字节以满足对齐要求。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • [Spring] Spring事务与事务的传播
  • 以下关于revision历史版本说法正确的是:
  • C语言-使用指针数组作为函数参数,实现对10个字符串进行排序
  • 海南云亿商务咨询有限公司引领抖音电商新潮流
  • 如何高效记录并整理编程学习笔记
  • rsync远程同步服务
  • SpringBoot解决创建项目无法选择JDK8和JDK11
  • 互斥锁以及进程间通信
  • 无人机之飞控系统基本功能
  • 遗传算法与深度学习实战(4)——遗传算法详解与实现
  • 视觉SLAM第六讲
  • vue3项目中使用 vue-i18n国际化插件,实现多语言效果
  • 响应式Web设计:纯HTML和CSS的实现技巧
  • Dapp链游如何应对DDoS攻击的全方位策略
  • PHP概述、环境搭建与基本语法讲解
  • 【剑指offer】让抽象问题具体化
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • CentOS从零开始部署Nodejs项目
  • css的样式优先级
  • ESLint简单操作
  • es的写入过程
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • Java教程_软件开发基础
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • Redis的resp协议
  • REST架构的思考
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 高性能JavaScript阅读简记(三)
  • 面试遇到的一些题
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​​​【收录 Hello 算法】9.4 小结
  • ​业务双活的数据切换思路设计(下)
  • #if #elif #endif
  • #Linux(make工具和makefile文件以及makefile语法)
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • %@ page import=%的用法
  • (C++17) optional的使用
  • (C++17) std算法之执行策略 execution
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (十八)三元表达式和列表解析
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (转) Android中ViewStub组件使用
  • (转)甲方乙方——赵民谈找工作
  • (转载)hibernate缓存
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • ***详解账号泄露:全球约1亿用户已泄露
  • ./configure、make、make install 命令
  • .ai域名是什么后缀?
  • .net Stream篇(六)
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • @antv/g6 业务场景:流程图
  • [ Linux ] git工具的基本使用(仓库的构建,提交)