为什么地址的顺序与代码中的变量不一样呢?
保证结构中的第一个元素位于与结构本身相同的位置(如果它们是某个元素的成员),但其他元素不能保证按任何顺序排列。通常,编译器会对它们进行适当的排序,以允许它使用最少的空间。对于局部变量,它们位于内存中的位置完全取决于编译器。它们可能都位于同一个区域(可能是因为它利用了本地的优势),或者它们可能都在地图上(如果您有一个糟糕的编译器)。
每个地址都是偶数?
它把它们放在词的边界上。这使得内存访问比没有放在字边界上的内存更快。例如,如果将a放在一个单词的最后一个字节上,另一个单词的第一个字节上:
代码语言:javascript复制| WORD 1 | WORD 2 |
|--------|--------|--------|--------|--------|--------|--------|--------|
| a[0] | a[1] |然后访问a[0],然后访问a[1],将需要将2个单词加载到缓存中(每个缓存丢失)。沿着一个词的边界:
代码语言:javascript复制| WORD 1 |
|--------|--------|--------|--------|
| a[0] | a[1] |a[0]上的缓存丢失将导致同时加载a[0]和a[1] (减少不必要的内存带宽)。这利用了局部性原则。虽然语言当然不需要它,但它是编译器所做的一种非常常见的优化(除非您使用预处理器指令来阻止它)。
在您的示例中(按其顺序显示):
代码语言:javascript复制3734044 b[0]
3734045 b[1]
3734046 b[2]
3734047 -----
3734048 a[0]
3734049 a[1]
3734050 -----
3734051 -----
3734052 arg
3734053 -----
3734054 -----
3734055 -----
3734056 f[0]
3734057 f[1]
3734058 f[2]
3734059 f[3]
3734060 f[4]
3734061 f[5]
3734062 f[6]
3734063 f[7]
3734064 f[8]
3734065 f[9]
3734066 f[10]
3734067 f[11]
3734068 f[12]
3734069 -----
3734070 -----
3734071 -----
3734072 e[0]
3734073 e[1]
3734074 e[2]
3734075 e[3]
3734076 e[4]
3734077 e[5]
3734078 e[6]
3734079 e[7]
3734080 c[0]
3734081 c[1]
3734082 c[2]
3734083 c[3]
3734084 c[4]
3734085 c[5]
3734086 -----
3734087 -----
3734088 d[0]
3734089 d[1]
3734090 d[2]
3734091 d[3]
3734092 d[4]假设没有为这些漏洞分配其他数据,那么无论您在编译器中拥有什么设置,都会确保您的所有数组都从一个word边界开始。这并不是说它在数组之间添加空间(正如您所看到的,e和c之间没有空格),而是第一个元素必须位于单词边界上。这是具体的实现,而不是标准所要求的。