在C语言程序开发中,有时有经验的程序员会提起“内存对齐”一词,事实上,这也是C语言中结构体的 size 不等于它所有成员 size 之和的原因(C语言中的结构体的size,并不等于它所有成员size之和,为什么?),那么,C语言程序为什么要“内存对齐”呢?

C语言程序为什么要“内存对齐”呢?

为什么要“内存对齐”?

C语言编译器在处理代码时,常常会将一些变量的内存对齐,这其实主要是因为底层处理器的限制。对于多数处理器而言,每次访问的数据并不是越少越好:例如,有的处理器每次访问 4 个字节数据,要比访问 1 个字节数据效率高得多。

针对这样的情况,一些C语言编译器会将代码中的变量地址对齐,目的就是让处理器能够更加高效的访问这些变量。甚至有些严格的处理器或者系统,在处理未进行内存对齐的数据时,根本无法正常运行(bus error 等)。

为什么要“内存对齐”?

因此,对于C语言程序中的一些数据而言,进行“内存对齐”至少有以下几点好处:

程序的执行效率提高

现代处理器一般都有多个级别的高速缓存,处理器访问这些高速缓存里的数据的效率要比访问内存里的数据效率高得多(就像处理器访问内存里的数据,比访问磁盘里的数据效率高得多一样。)。

就像上面介绍以的一样,一般来说,CPU 总是以字大小(32 位处理器上常常为 4 个字节)访问数据,所以如果数据没有内存对齐,CPU 访问这些数据时,可能就需要执行更多次的读取操作才行。在这样的机器上,读取 2 个字节数据往往比读取 4 个字节数据慢得多。

CPU 总是以字大小访问数据

假设在C语言程序开发中,我们在内存里定义了下面这样的数据结构:

struct mystruct { char c; // one byte int i; // four bytes short s; // two bytes}

在 32 位处理器上,上述数据结构可能会被按照下图这样排列(即所谓的“内存对齐”):

上述数据结构可能会被按照这样排列

此时,处理器访问结构体 mystruct 的任意一个成员都只需一次访问。如果没有内存对齐,mystruct 的各个成员在内存中紧密排列,如下图:

在内存中紧密排列

此时,如果处理器需要从 0x05 处读取 16 位数据,处理器将不得不从 0x04 处读取一个字(这里等于 4 字节),然后左移一个字节,将结果放入 16 位寄存器中。

如果处理器需要从 0x01 处读取 32 位数据,效率就降低至少 2 倍了:处理器不得不从 0x00 处读取一个字,并且左移一个字节,然后从 0x04 处再读取一个字,并且右移 3 个字节,最终使用 OR 位运算将两次读取结果拼接,才能达成目的。

访问范围提高

访问范围提高

对于任意给定的地址空间,如果体系架构可以确定 2 个 LSB 总是 0(例如 32 位机器),那么它可以访问 4 倍多的内存(2 个位能够表示 4 个不同状态)。从一个地址中去掉 2 个 LSB,将得到 4 字节的内存对齐,或者说“跨距”,因为地址每增加一,它就有效的增加 bit 2,而不是 bit 0。(鉴于低 2 位总是 00)

这甚至会影响系统的物理设计:如果地址总线的需要少 2 位,CPU 上的管脚就可以少 2 个。

原子性的保障

前面提到 CPU 每次访问数据的宽度是一个字,如果C语言程序中的数据总是内存对齐的,那么 CPU 访问数据总是原子性的,这对于许多无锁数据结构和其他并发需求的正确操作至关重要。

小结

事实上,本节只是粗浅讨论,处理器的内存系统比这里描述的要复杂得多,涉及的内容也要复杂得多。不过,我们至少已经知道,在C语言程序中坚持内存对齐还是有很多好处的。

点个赞再走吧

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。

未经许可,禁止转载。

c# 结构体 4字节对齐_C语言程序员们常说的“内存对齐”,究竟有什么目的?相关推荐

  1. 结构体前面加星号_C语言中带星号的类型指针有哪些特性

    C语言中带星号的类型指针有哪些特性 指针是什么?很多人说,指针就是地址,那这么说的人肯定是对指针有所了解,他们这么说也不能说全错,我只能在这里说:"他们并没有真正学会指针,如果想学好指针,请 ...

  2. c语言将结构体存储在数组中,结构体数组方法用法 _C语言-w3school教程

    C语言 的 结构体数组 在C语言编程中可以将一系列结构体来存储不同数据类型的许多信息. 结构体数组也称为结构的集合. 我们来看一个数组结构体的例子,存储5位学生的信息并打印出来.创建一个源文件:str ...

  3. c语言结构体数组存入文件_c语言怎么用文件保存和读取 结构体数组/

    文本方式读写#include"stdio.h"#include<stdlib.h>#defineSIZE5structstudent{charID[10];charNa ...

  4. c语言结构体变量所占字节计算,【C语言】结构体占用字节数及存储与空间分配...

    我们都知道在数据类型中,char类型占1个字节,short占2个字节,int占4个字节,long占8个字节等等. 在计算结构体大小时需要考虑其内存布局,结构体在内存中存放是按单元存放的,每个单元多大取 ...

  5. C语言中如何计算结构体的字节大小

    结构体内存对齐 在计算结构体所占字节的大小时,不要直观地累加结构体内成员的字节大小,实际结构体存放在内存中是有一定的规则的,这里涉及的规则就是内存对齐原则. 声明一个结构体stu struct stu ...

  6. linux中c语言结构体详解,Linux C语言结构体-学习笔记

    Linux C语言结构体简介 前面学习了c语言的基本语法特性,本节进行更深入的学习. 预处理程序. 编译指令: 预处理, 宏定义, 建立自己的数据类型:结构体,联合体,动态数据结构 c语言表达式工具 ...

  7. c语言结构体成员变量私有化,C语言中结构体变量私有化详解

    C语言中结构体变量私有化详解 背景介绍 操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚 ...

  8. java 网络字节序转主机字节序_C语言高级编程——网络编程技术

    了解什么是网络编程 熟悉七层网络模型 熟悉网络开发中使用到的函数 掌握TCP协议类程序开发 掌握UDP协议类程序开发 计算机本身是不会进行网络通信的,所以要想使通过软件进行网络通信,必须制定相应的规则 ...

  9. codeup 结构体输入输出问题 B: C语言11.2

    codeup结构体输入输出 问题 B: C语言11.2 题目描述 定义一个结构体student,存储学生的学号.名字.性别和年龄,读入每个学生的所有信息,保存在结构体中,并输出.结构体student的 ...

最新文章

  1. grep查找时,去掉grep本身那一条
  2. 中国石化行业节能减排行业发展动态与运营前景规划展望报告2022年
  3. 干货 | 一文概览主要语义分割网络,FCN、UNet、SegNet、DeepLab 等等等等应有尽有
  4. ThreadLoacl,InheritableThreadLocal,原理,以及配合线程池使用的一些坑
  5. react学习(3)----不能在该位置用setstate
  6. 我更爱荷叶freeeim
  7. Adsutil.vbs 在脚本攻击中的妙用
  8. 入门不简单(《Beginning C# Objects中文版》书评)
  9. [C++]实现10以内整数的简单科学计算器
  10. vue-router: 路由传参
  11. 最新30套Java项目实战
  12. 理解http的幂等性
  13. OpenCV C++案例实战二十《银行卡号识别》
  14. html 页面的分析与设计,HTML+CSS网页设计教程
  15. 老外用VB6写的Windows驱动备份软件
  16. word压缩软件,免费
  17. 7-46 新浪微博热门话题 (30分)
  18. WiFi测试规范总结
  19. Form表单验证神器: BootstrapValidator常见的坑,input框的value值改变二次验证不了?
  20. 第二十四天:2019年第九届MathorCup高校数学建模挑战赛A题

热门文章

  1. Python高性能HTTP客户端库requests的使用
  2. 3月份Github上最热门的Python开源项目
  3. 用python制作一款录屏小工具
  4. Python正则表达式中的贪婪和非贪婪
  5. Mac Pro m1 安装 brew/eclipse/visual stadio code/nodejs/git
  6. 深度学习-tensorflow1.x:平均值(reduce_mean)与求和(reduce_sum) 小白理解 代码实现 Tensorflow1.x 和 Numpy
  7. kibana 查询_Exceptionless服务端+kibana部署实时日志纪要
  8. win7找回开机密码_电脑密码忘记了?教你四步轻松找回电脑开机密码
  9. 王道 —— 进程互斥的软件实现方法
  10. leetcode - 343. 整数拆分