目录 Table of Contents
结构的存储
结构的存储-1
结构
结构的定义, 一块连续分配的内存区域, 内部的元素通过名字去访问, 而且内部元素可以是不同的数据类型.
里面元素是连续存放的
下面是访问结构的 C 语言代码 :
struct rec{
int i;
int a[3];
int *p;
}
void set_i(struct rec *r, int val)
{
r->i = val;
}
汇编代码如下 :
; %eax = val
; %edx = r
movl %eax, (%edx) ; Mem[r] = val
结构中元素地址的计算
还是上面那个结构, 我们要计算 里面第二个元素 a 里面某个下标为 idx 的元素的地址
int *find_a(struct rec *r, int idx)
{
return &r->a[idx];
}
我们先画出 layout :
看图就知道, 针对这个 idx 的访问, 就是它的首地址, 加上一个 4, 因为 i 占了 4 个字节, 这就相当于访问了一个数组, 数组首地址是 r + 4, 找到数组之后就根据索引和每个元素的大小来访问我们的目标元素
汇编代码如下 :
; %edx = idx
; %edx = r
leal 0(, %ecx, 4), %eax ; 4 * idx
leal 4(%eax, %edx), %eax ; r + 4 * idx + 4
每个元素在结构中的相对地址, 编译时就已经确定了.
续前
再来一个复杂点的, 这么个故意构造出来的运算, 把三个元素的访问都涉及到了
还是上面那个结构
void set_p(struct rec *r)
{
r->p = &r->a[r->i];
}
把 r + i 作为 index 去访问 a 里面的这个元素, 然后把这个元素地址算出来, 赋值给 p
; %edx = r 结构首地址
movl (%edx), %ecx ; r->i 首先把 i 元素的值取出来, 放到 ecx 里面去
leal 0(, %ecx, 4), %eax ; 4 * (r->i) 计算 r 里面 a 的这个元素的地址
leal 4(%edx, %eax), %eax ; r + 4 + 4 * (r->i)
movl %eax, 16(%edx) ; Update r->p
结构的存储-2
数据存储位置对齐
现在计算机系统, 对这些元素的存储都有一个位置对齐的要求
位置对齐就是, 假设你这个数据类型的 size 为 k, 那么它的存储地址必须是 k 的整数倍.
当然, 不同的系统的要求都略有不同
为什么要这样呢, 因为计算机访问内存一般是以内存块为单位的, 块的大小是地址对齐的.
如果你不要求基本数据位置上的对齐, 数据访问地址跨越 "块" 的边界会引起额外的内存访问. 比如说一个 int, 它位于 2 个内存块之间, 你要取这个 int, 你就要两次访问内存
C 语言编译器会在各个元素之间插入额外的空间, 来满足不同元素的对齐要求
x86-32 下不同元素的对其要求
基本数据类型 :
如果大小为 1byte, 比如 char, 就没有任何对齐要求
如果大小为 2 byte, 比如 short, 就需要 2 字节对齐, 地址最后一位为 0
如果大小为 4 byte, 比如 int float char*, 要求 4 字节对齐, 地址最后两位为 0
如果是 8 byte, double 类型, 看情况. windows 系统地址后三位为 0, 8 字节对齐. linux 系统为 4 字节对齐, 地址后两位为 0.
-86-64 下不同元素的对齐要求
1 byte, 2 byte, 4 byte 同 x86-32
8 byte 大小比如 double, windows&linux 都是要求 8 字节对齐
16 byte 大小的 long double, linux 为 8 对齐, 地址最后三位为 0.
结构的存储-3
结构的对齐存储要求
- 必须满足结构中各个元素的对齐要求
首先一个结构给你了, 结构当中每个元素该怎么存就怎么存, 每个元素该怎么对齐还是怎么对齐.
-
结构自身的对齐要求, 等同于其各个元素中对齐要求最高的那个, 设为 k 字节
-
结构的起始地址和结构长度必须是 k 的整数倍
结构的存储-4
结构自身的对齐要求
刚才说过, 结构里面的元素就是应该怎么对齐就是怎么对齐
结构本身也有对齐要求, 结构自身的对齐要求, 就参照它里面各个元素对齐要求最严格的那一个
结构内元素不同的先后顺序
我们声明一个结构, 结构里元素不变, 但是这次我们改一下它们在里面的顺序, 这就会对结构在内存里面的布局产生一些影响.
结构数组的存储
结构数组
首先计算数组元素 (即结构) 的地址
然后访问该结构中的元素
小结
结构起始地址的对齐要求, 等同于该结构各个元素中对齐要求最高的那个
结构当中的元素, 该怎么对齐就怎么对齐
结构的长度必须是 K 的整数倍
联合
联合和结构有点像, 区别是结构元素是一个挨着一个放的
联合是里面的元素共享同一块内存, 假设有个联合, 里面有 3 个元素, 你可以理解为这 3 个元素是叠在一起放的
所以说联合的尺寸, 完全是里面最大的层面的大小来决定的
联合成员共享同一块大小的内存, 一次只能使用其中的一个成员
小结_
-
C 语言数组的汇编访问
-
连续存储
-
访问代码优化
-
无边界检查
-
-
结构
-
对齐要求
-
以及相应的汇编代码
-
-
联合