user-0 提问: 请问一个字节对齐的问题？

回复:
user: user-1
content: 计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构…… 搜“地址总线” 对浮点数的处理是CPU内部的浮点处理单元负责而非CPU内部的通用运算器负责。

user: user-2
content: 实际对32位系统，按8字节对齐只会浪费空间，这里vs系列做的不够好，gcc下32位系统默认按4字节对齐，这个才是最佳的选择

user: user-3
content: 内存对齐，主要是考虑到CPU的存取速度。  主要是因为现代计算机都使用了Cache。因为CPU直接访问内存是比较慢的，所以将平时经常使用的内容存放到Cache里面。  Cache是通过一些Cache block来组织的，每一个Cache block一般包含16个字节，32个字节或64个字节等。 比如某个计算机一级Cache的Cache block长度是32个字节，那么每段Cache block总是会包含32个字节对齐的一段内存。  现在有一个double，8字节，如果它的地址不是8字节对齐的，而是被允许进行4字节对齐了，那么就有可能访问它的时候，需要使用两个Cache block，也就是说前4个字节在前一个Cache block上，后4个字节在后一个Cache block上。那么访问两次肯定比访问一次慢。同时这个时候，这个数据没有在Cache里面的机会会增加，因为你允许了这个double4字节对齐，而正好最后一个Cache block上空有4字节的空余，于是机器先把前4字节读到Cache了。但是如果这样的话，当cpu需要使用这个double计算的时候，发现这个double还差4个字节不在，还需要将数据从内存调入Cache，会非常慢，降低了计算的速度。 而如果double，你要求就是8字节对齐，那么要么它就是直接全部读到Cache ，要么就是比如Cache空余不足8字节，Cache满了，那么就一个字节也不会读进去， 等空出来8个字节才会读到Cache ，不会出现Cache 空了4个字节的时候读了一个数据的一半的情况。  摘录《Professional Assembly Language》：里面是这么说的 Memory access is one of the slowest functions the processor performs. When writing assembly language programs that require high performance, it is best to avoid memory access as much as possible. Whenever possible, it is best to keep variables in registers on the processor. Register access is highly optimized for the processor, and is the quickest way to handle data. When it is not possible to keep all of the application data in registers, you should try to optimize the memory access for the application. For processors that use data caching, accessing memory in a sequen- tial order in memory helps increase cache hits, as blocks of memory will be read into cache at one time. One other item to think about when using memory is how the processor handles memory reads and writes. Most processors (including those in the IA-32 family) are optimized to read and write memory locations in specific cache blocks, beginning at the start of the data section. On a Pentium 4 processor, the size of the cache block is 64 bits. If you define a data element that crosses a 64-bit block boundary, it will require two cache operations to retrieve or store the data element in memory. To solve this problem, Intel suggests following these rules when defining data: ❑ Align 16-bit data on a 16-byte boundary. ❑ Align 32-bit data so that its base address is a multiple of four. ❑ Align 64-bit data so that its base address is a multiple of eight. ❑ Avoid many small data transfers. Instead, use a single large data transfer. ❑ Avoid using larger data sizes (such as 80- and 128-bit floating-point values) in the stack. Aligning data within the data section can be tricky. The order in which data elements are defined can be crucial to the performance of your application. If you have a lot of similarly sized data elements, such as integer and floating-point values, place them together at the beginning of the data section. This ensures that they will maintain the proper alignment. If you have a lot of odd-sized data elements, such as strings and buffers, place those at the end of the data section so they won’t throw off the alignment of the other data elements. 大意是这么说的： 内存访问是处理器执行的功能里很慢的一个，所以要写出高性能的程序，就要尽量减少内存访问。 对于使用数据缓存的处理器，按顺序访问内存可以提高缓存命中率，因为每次有一整段的内存被读取到缓存里。 大多处理器（包括IA-32系列）被优化而对特定的缓存块进行内存读写。在奔四处理器上，缓存块大小是64位。如果你定义了一个跨过64位界限的数据，它会执行两次缓存操作来提取或存储此数据。 为解决这个问题，Intel建议在定义数据时遵守那几条规则，即把n字节的数据定义在n的倍数的内存地址上进行对齐。 所以，对于大量大小相似的数据元素（如整型、浮点型）最好把它们一起放到开头；而有些奇数大小的数据（如字符串、缓冲区），最好把它们放到后面。

user: user-4
content: 1.首先在计算机的体系结构层次上，存储系统是多级的，在存储器和cpu的寄存器之间，有多个cache(高速缓存)。如果存储器的存储单位是“字-word-32bit-4byte"的话，存储器上一级的cache的存储单位会是n(=2^k，2的k次方，k>=2)个”字“（称为一个块-block）  2.当存储器中的数据是8byte时，按8的整数倍起始地址对齐的话，这个数据向上级cache传送是会保证在一个块中  3.当存储器中的数据是8byte时，按4的整数倍起始地址对齐的话，这个数据一定有可能分布在前一块的最后和后一块的最前。 即对这个8byte数据访问时，要传送两个块到cache中----效率如何？

user: user-5
content: 引用 楼主 waitianlou 的回复:最近在看字节对齐的问题，有一个疑问就是为什么变量要放在和自身所占字节整数倍的起始位置上？ 如果说字节对齐是为了cpu的总线读取更有效率的话，那么对于一个8位的double型数据来说，为什么要是在8的整数倍地址上呢？在4的整数倍上有什么问题呢？ 比如说： 一个double值： 在0x0004地址上存放，那么就占了0x0004-0x000B 在0x0008地址上存放，那么就占了0x0008-0x000F 对于一个32位的cpu来说，两者有不同的么？  是CPU的一次读取字节的整数倍，不是变量自身所占字节的整数倍。

user: user-6
content: 感觉大伙没有明白楼主想问的主要问题是啥。 楼主貌似只是想知道首地址为什么必须和8对齐，而不是和4对齐即可，衍生一下，为什么“首地址能够被其最宽基本类型成员的大小所整除”。 不知道我对楼主的的问题的理解是否正确，对于字节对齐的背景知识，这个网上能搜到很多~~~

user: user-7
content: 引用 2 楼 91program 的回复:字节对齐，不同编译器会做出不同的处理，没有强制的要求。就是同一编译器，是否字节对齐一般都是可以设置的。  对齐是体系结构的事，编译器只是要求跟体系结构配合

user: user-8
content: 字节对齐，不同编译器会做出不同的处理，没有强制的要求。就是同一编译器，是否字节对齐一般都是可以设置的。

user: user-9
content: 引用 楼主 waitianlou 的回复:最近在看字节对齐的问题，有一个疑问就是为什么变量要放在和自身所占字节整数倍的起始位置上？ 如果说字节对齐是为了cpu的总线读取更有效率的话，那么对于一个8位的double型数据来说，为什么要是在8的整数倍地址上呢？在4的整数倍上有什么问题呢？ 比如说： 一个double值： 在0x0004地址上存放，那么就占了0x0004-0x000B 在0x0008地址上存放，那么就占了0x0008-0x000F 对于一个32位的cpu来说，两者有不同的么？  字节对齐这种事是给cpu方便的，像mips如果直接去访问 末尾非0 4 8 c的地址会有额外的开销，老一点的编译器甚至直接就不允许写出非对齐访问的汇编代码。

user: user-10
content: 楼主可以看看这家伙的blog。  c/c++中内存对齐完全理解，看完不理解请砍我(http://www.cnblogs.com/xylc/p/3780907.html) 以及 http://blog.sina.com.cn/s/blog_67c294ca01012qbu.html