C/C++ 内存对齐规则

2024-08-30 19:58
文章标签 c++ 内存 规则 对齐

本文主要是介绍C/C++ 内存对齐规则,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

记录学习c++中遇见的一些常见的易错的知识点等

最近在牛客网刷题的时候经常会遇到关于内存对齐的问题

有以下的代码, 结果会输出什么呢,我们知道int是4个字节,short是2个字节,char是1个字节,那么二者是不是都是一样的,都是7呢?
其实都不是,我的编译器默认是4字节对齐,所以第一个是12,第二个是8

#include <stdio.h>struct A{char a;int b;short c;
};struct B{short c;char a;int b;
};int main(){printf("sizeof A ==> %d\nsizeof B ==> %d\n", sizeof(A), sizeof(B));return 0;
}

这里写图片描述

这里可以先看下内存对齐的规则:
1. 对于结构体的各个成员,假设第一个变量起始地址是0, 那么后面的变量偏移的地址必须是Min(#pragma pack, 该变量的字节大小)的最小整数倍。
2. 在所有的成员对齐之后,结构体本身也是要对齐的, 对齐规则是Min(#pragma pack, 该结构体的最达字节成员)的最小整数倍。

其中#pragma pack(x) 是指定编译器按照x字节进行对齐

上面的规则也可以通俗简单的这样理解, 就是内存不是我们想象的一个一个的随意的放,而是组织为4(假设对齐是4个字节)个字节,4个字节,这样的“小结构”,所以对于A结构体, char a;首先占据一个字节,4个字节的“小结构”就剩下了3个, 可是后面来了个int b; b是4个字节的, 剩余的3个字节放不下,就得往后挪动3个字节,到达一个新的“小结构”的开始处,同理,short c;占据了4个字节的2个,然后再由内存对齐规则2,最终占据4+4+4 = 12字节。B结构体,short c;先占据4个 “小结构”的中的2个,然后就是char a;占据short c;剩余的2个字节中的一个, 再接着就是int b;往后挪动一个字节,再独自占据着4个字节,一个就是4+4 = 8 个字节了。

接下来 我们改变 对齐的字节数, 看看结果是不是和我们想的一样

#include <stdio.h>//对齐是1字节
#pragma pack(1)
struct A{char a;int b;short c;
};struct B{short c;char a;int b;
};int main(){printf("sizeof A ==> %d\nsizeof B ==> %d\n",sizeof(A), sizeof(B));return 0;
}

列表内容

然后再是2

#include <stdio.h>
#pragma pack(2)
struct A{char a;int b;short c;
};struct B{short c;char a;int b;
};int main(){printf("sizeof A ==> %d\nsizeof B ==> %d\n", sizeof(A), sizeof(B));return 0;
}

这里写图片描述

验证了对齐的规则确实如此

再看看对齐的规则2

#include <stdio.h>struct A{char a;int b;short c;
};struct B{short c;char a;int b;
};struct C{short b;char c;
};int main(){printf("sizeof A ==> %d\nsizeof B ==> %d\nsizeof C ==> %d\n",sizeof(A), sizeof(B), sizeof(C));return 0;
}

这里写图片描述

C结构体 ,按照规则1计算的结果就是3, 但是别忘记规则2, 整体也是得对齐的所以就是4


最后,为什么需要内存对齐,大概的原因就是
1. 移植
2. cpu的操作效率高

这篇关于C/C++ 内存对齐规则的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1121780

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

Python之变量命名规则详解

《Python之变量命名规则详解》Python变量命名需遵守语法规范(字母开头、不使用关键字),遵循三要(自解释、明确功能)和三不要(避免缩写、语法错误、滥用下划线)原则,确保代码易读易维护... 目录1. 硬性规则2. “三要” 原则2.1. 要体现变量的 “实际作用”,拒绝 “无意义命名”2.2. 要让

Python内存管理机制之垃圾回收与引用计数操作全过程

《Python内存管理机制之垃圾回收与引用计数操作全过程》SQLAlchemy是Python中最流行的ORM(对象关系映射)框架之一,它提供了高效且灵活的数据库操作方式,本文将介绍如何使用SQLAlc... 目录安装核心概念连接数据库定义数据模型创建数据库表基本CRUD操作创建数据读取数据更新数据删除数据查

C++读写word文档(.docx)DuckX库的使用详解

《C++读写word文档(.docx)DuckX库的使用详解》DuckX是C++库,用于创建/编辑.docx文件,支持读取文档、添加段落/片段、编辑表格,解决中文乱码需更改编码方案,进阶功能含文本替换... 目录一、基本用法1. 读取文档3. 添加段落4. 添加片段3. 编辑表格二、进阶用法1. 文本替换2

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别

深入浅出Java中的Happens-Before核心规则

《深入浅出Java中的Happens-Before核心规则》本文解析Java内存模型中的Happens-Before原则,解释其定义、核心规则及实际应用,帮助理解多线程可见性与有序性问题,掌握并发编程... 目录前言一、Happens-Before是什么?为什么需要它?1.1 从一个问题说起1.2 Haht

k8s容器放开锁内存限制问题

《k8s容器放开锁内存限制问题》nccl-test容器运行mpirun时因NCCL_BUFFSIZE过大导致OOM,需通过修改docker服务配置文件,将LimitMEMLOCK设为infinity并... 目录问题问题确认放开容器max locked memory限制总结参考:https://Access

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法