在现代计算机中,内存是字节导向的。每个字节都有自己的地址,并可以从RAM中单独获取。为了您的程序,您可以假设获取一个字(word)就像以任意顺序获取组成它的字节,然后在您加载到的寄存器中将它们组装成一个字。
请注意,这是一个抽象概念。内存芯片通常被布线方式连接,一次会取出8个或更多字节。CPU具有一些电路来将所有这些东西从机器代码中抽象出来。但是,这种抽象是不完全的,这会导致许多效果:
- 如果数据没有对齐到它的对齐要求,内存访问可能需要额外的周期,因为数据跨越了比必要的更多的字。通过充分对齐数据可以避免这种惩罚。
- 当获取或写入对齐的数据时,在硬件中将其转换为单个取/存储。这样的取/存储是原子的,这是并发代码中的一个重要属性。当获取或写入未对齐的数据时,需要多个取/存储,操作不再是原子的。
- 一些CPU根本不支持读/写非对齐内存,因为这简化了电路设计。这种限制在现代硬件中变得越来越少见。
那么现在,针对您的问题:
1) 因此,无论我给出什么地址,它都会读取4个字节吗?如果我在地址x处有一个简单的char,它会从该地址读取4个字节,然后进行某些奇怪的操作以获得一个字节吗?
也许。这取决于您使用的硬件。但是,是的,如果您请求一个字节,则会只获取一个字节。您不应该关心硬件读取多少字节才能为您提供那一个字节。
2) 如果是这样,那么一个字符串(字符序列)的大小为 n_chars * 4 字节吗?我很确定不是这样,但我应该如何解释“将始终读取其字边界”呢?
一个字符串通常是 n_chars
字节大小。当你从字符串中读取一个字符时,你得到一个字节。硬件可能会读取更多的字节来满足你的请求,但这不是你需要关心的事情。请注意,Windows 有时使用占用每个字符两个字节的 UTF-16 字符串,但这种趋势并没有真正流行起来。
3) 内存对齐似乎只涉及数据结构。为什么?内存在其他地方未对齐吗?我指的是物理、虚拟、内核空间等。
内存对齐在考虑 RAM 中的数据时很重要。无论内存是在内核还是用户进程中使用,都不重要。MMU 通常以保留对齐方式的方式映射内存,因此使用物理或虚拟内存并不重要。磁盘上的数据没有这些对齐要求,但由于所使用的存储器的扇区大小,可能适用于其他性能特征。
4) 为什么只能将32位值存储在可被4整除的地址上?我的意思是,我知道最终只会读取32位,但为什么不能从奇数地址读取32位?这里有什么限制呢?
如果您从奇数地址读取32位,则根据您的CPU和操作系统,可能会发生以下情况:
- 它可以正常工作
- 它可以正常工作,但速度会稍慢
- CPU会默默地忽略低2位,并从相应对齐的地址读取(这在现今很少见)
- CPU会抛出异常,如果您不处理它,程序就会崩溃
- CPU会抛出异常,操作系统会捕获该异常以为您模拟内存访问。
通常情况下,您不应假设会发生哪种情况。永远不要编写读取未对齐数据的代码。如果需要读取未对齐数据,请考虑逐个字节读取,然后手动重新组装所需的数据。