《C语言编程魔法书:基于C11标准》——2.4 地址与字节对齐

2.4 地址与字节对齐

由于C语言是一门接近底层硬件的编程语言,它能直接对存储器地址进行访问(当前大部分处理器在操作系统的应用层所访问到的逻辑地址,而部分嵌入式系统由于不含带存储器管理单元,因此可直接访问物理地址)。在计算机中,所谓“地址”就是用来标识存储单元的一个编号,就好比我们住房的门牌号。没有门牌号,快递就没法发货;如果门牌号记错了,那么快递就会把货物送错地方。计算机中的地址也是一样,我们为了要访问存储器中特定单元的一个数据,那么我们首先要获悉该数据所在的地址,然后我们通过这个地址来访问它。访问存储器,我们也简称为“访存”(Memory Access)。访问地址,我们也简称为“寻址”(Addressing)。我们在图2-1中也看到,一般计算机架构中都会有地址总线和数据总线。CPU先通过地址总线发送寻址信号,以指定所要访问存储器单元的地址。然后再通过数据总线向该地址读写数据,这样就完成了一次访存操作。这好比于快递送货,我们先打电话告诉快递通信地址,然后快递员把货送到该地址(写数据),或者去该地址拿货(读数据)送到别家。
一般对于32位系统来说,处理器一次可访问1个(8比特)字节、2个字节或4个字节。当访问单个字节时,对CPU不做对齐限制;而当访问多个字节时,比如要访问N个字节,由于计算机总线设计等诸多因素,要求CPU所访问的起始地址满足N个字节的倍数来访问存储器。如果在访问存储器时没有按照特定要求做字节对齐,那么可能会引发访存性能问题,甚至直接导致寻址错误而引发异常(引发异常后通常会导致当前应用意外退出,在嵌入式系统中可能就直接死机或复位)。
下面我们给出一张图2-8来描述,看看一般对32位系统而言如何正确地做到访存字节对齐。
图2-8展示了如何正确对齐访问1个字节、2个字节和4个字节的情况。图中画出了6个存储单元内容,地址低16位从0x1000到0x1005,每个存储单元为1个字节。对于仅访问1个字节的情况,图2-8所有地址都能直接访问并满足字节对齐的情况。对于一次访问2个字节的情况,要满足对齐要求,只能访问0x1000、0x1002、0x1004等必须要能被2整除的地址。对于一次访问4字节的情况,要满足对齐要求,则只能访问0x1000、0x1004等必须要能被4整除的地址。

然而,并不是说要访问多少字节,就必须要保证访问能被多少整除的地址才能满足对齐要求。如果一次访问8字节,对于32位系统而言,通过32位通用目的寄存器来读写存储器的话,某些CPU会自动将8字节的访存分为两次进行操作,每次为4字节,因此只要保证4字节对齐就能满足对齐要求。这些都根据特定的处理器来做具体处理。
就笔者用过的一些处理器而言,像x86、ARM等处理器,当访存不满足对齐要求时并不会引发总线异常,但是访问性能会降低很多。因为原本可一次通信的数据传输可能需要拆分为多次,并且前后还要保证数据的一致性,所以还可能会有锁步之类的操作。而像Blackf?in DSP则会直接引发总线异常,导致整个系统的崩溃(如果不对此异常做处理的话)。另外,像ARMv5或更低版本的处理器,在对非对齐的存储器地址进行访问时,CPU会先自动向下定位到对齐地址,然后通过向右循环移位的方式处理数据,这就使得传输数据并不是原本想一次传输的数据内容,也就是说写入的或读出的数据是失真的。比如,根据图2-8所示内容,如果我们要对一款ARM7EJ-S处理器(ARMv5TEJ架构)从地址0x1002读4字节内容,那么实际获取到的数据为0x02010403;而在x86架构或ARMv7架构的处理器下,则能获得0x06050403。

时间: 2024-11-05 11:10:45

《C语言编程魔法书:基于C11标准》——2.4 地址与字节对齐的相关文章

《C语言编程魔法书:基于C11标准》—— 导读

前 言 为什么要写这本书 本人在2001年上了大学本科,读计算机科学与技术专业.在第一年的上半学期,对计算机编程还没什么感觉.但是就在考"C语言程序设计"这门专业课的前一个月,感觉这门课学了那么久几乎什么都不会,可把我急坏了.然后就在这短短一个月的时间里又是看书,又是上机实验,终于考了70多分,算是过关了--不过奇怪的是在考试结束后,就发现自己对编程有了感情.到了大二,我们上"数据结构"所使用的教材是基于C++编程语言的,因为之前没学过C++语言,所以只能自学.而在

《C语言编程魔法书:基于C11标准》——导读

前 言 为什么要写这本书 本人在2001年上了大学本科,读计算机科学与技术专业.在第一年的上半学期,对计算机编程还没什么感觉.但是就在考"C语言程序设计"这门专业课的前一个月,感觉这门课学了那么久几乎什么都不会,可把我急坏了.然后就在这短短一个月的时间里又是看书,又是上机实验,终于考了70多分,算是过关了--不过奇怪的是在考试结束后,就发现自己对编程有了感情.到了大二,我们上"数据结构"所使用的教材是基于C++编程语言的,因为之前没学过C++语言,所以只能自学.而在

《C语言编程魔法书:基于C11标准》——2.9 本章小结

2.9 本章小结 本章大致介绍了计算机体系结构以及程序执行的大致流程,然后描述了整数以及浮点数在计算机中的存储方式,之后还介绍了地址与字节对齐.字符编码.处理器大端与小端字节序,以及按位逻辑运算和移位操作.由于这些知识都是学习C语言必备的,C语言中有相关语法与这些概念对应,所以各位最好能先理解.掌握这些基本知识,这样对后续学习C语言将有很大帮助.

《C语言编程魔法书:基于C11标准》——第3章 C语言编程的环境搭建3.1 Windows操作系统下搭建C语言编程环境

第3章 C语言编程的环境搭建 我们在第2章讲述了学习C语言所必需的一些预备知识.本章将给大家介绍常用桌面操作系统下的C语言环境搭建.这里所讲述的C语言编译器以及集成开发环境(IDE)都是可合法免费下载的,本书不鼓励各位使用盗版或破解软件,所以下面会列出下载这些合法免费软件的官方链接,大家把编程环境搭建完之后即可上机实践编程. 3.1 Windows操作系统下搭建C语言编程环境 Windows操作系统下默认不自带任何C语言编译器,大家必须从网上下载自己所需要的C语言编译器.如果各位想通过C语言开发

《C语言编程魔法书:基于C11标准》——第一篇 预备知识篇 第1章 C魔法概览1.1 例说编程语言

第一篇 预备知识篇 第1章 C魔法概览 本章内容主要对C编程语言(以下简称C语言)进行大体介绍,包括它的历史以及C语言标准的演化进程.然后介绍一下C语言编程思想,当前主流C语言编译器以及GNU语法扩展.最后简单介绍一下从用C语言编写程序到编译.构建一个可执行程序的大致过程. 计算机编程语言从对计算机硬件底层的抽象程度进行分类,可分为:机器语言.汇编语言以及高级语言.下面由底层到高层分别介绍这几种类别的编程语言. 1.1 例说编程语言 1)机器语言是直接通过十六进制数表示当前处理器架构的机器指令码

《C语言编程魔法书:基于C11标准》——第一篇 预备知识篇 第1章 C魔法概览 1.1 例说编程语言

第一篇 预备知识篇 第1章 C魔法概览 本章内容主要对C编程语言(以下简称C语言)进行大体介绍,包括它的历史以及C语言标准的演化进程.然后介绍一下C语言编程思想,当前主流C语言编译器以及GNU语法扩展.最后简单介绍一下从用C语言编写程序到编译.构建一个可执行程序的大致过程. 计算机编程语言从对计算机硬件底层的抽象程度进行分类,可分为:机器语言.汇编语言以及高级语言.下面由底层到高层分别介绍这几种类别的编程语言. 1.1 例说编程语言 1)机器语言是直接通过十六进制数表示当前处理器架构的机器指令码

《C语言编程魔法书:基于C11标准》——1.3 主流C语言编译器介绍

1.3 主流C语言编译器介绍 对于当前主流桌面操作系统而言,可使用Visual C++.GCC以及LLVM Clang这三大编译器.其中,Visual C++(简称MSVC)只能用于Windows操作系统:其余两个,除了可用于Windows操作系统之外,主要用于Unix/Linux操作系统.像现在很多版本的Linux都默认使用GCC作为C语言编译器.而像FreeBSD.macOS等系统默认使用LLVM Clang编译器.由于当前LLVM项目主要在Apple的主推下发展的,所以在macOS中,Cl

《C语言编程魔法书:基于C11标准》——1.4 关于GNU规范的语法扩展

1.4 关于GNU规范的语法扩展 GNU是一款能用于构建类Unix操作系统的计算机软件合集,由自由软件之父Richard Stallman开创,于1983年9月27日对外发布.GNU完全由自由软件(free software)构成.GNU语法扩展源自于GCC编译器,在1987年发布1.0版本,称为GNU C Compiler.随后,GCC编译器前端支持了C++.Objective-C/C++.Fortran.Ada.Java以及最近跃升的Go等编程语言,因此现在GCC被称为GNU Compile

《C语言编程魔法书:基于C11标准》——1.2 用C语言编程的基本注意事项

1.2 用C语言编程的基本注意事项 C语言的发明其实基于Unix操作系统.当时在C语言未面世之前,Dennis Ritchie所在的AT&T贝尔实验室用的Unix系统是完全用汇编语言写的.汇编语言的优势是直接面向处理器本身,能直接对底层硬件进行控制,充分发挥处理器的硬件能力.然而,它的缺陷也是显而易见的. 1.汇编语言的不足 首先,不可移植性.每种处理器,其指令集都大相径庭,比如ARM有ARM的指令集架构(ISA),Intel x86有x86的ISA,还有MIPS.Power(原来为PowerP