C5-复杂数据类型
复杂数据类型的机器级表示
数组
数组的分配和访问
- 数组存储在存储器中, 不存储在寄存器中.
- 存放地址使用基址(+比例变址(+位移)). 变址值存放在ECX中, ECX在循环体中增量.
- 数组定义在函数之外的静态区, 为一静态变量. 存放在可执行目标文件的数据段中.
- 数组定义在函数内, 为auto变量. 存放在栈中, 数组首地址用EBP定位.
- 数组存放以行优先, 按顺序存放每行的数值, 在每一行之内, 按照右到左的顺序存放数值


数组与指针
数组的目标数据类型和数组类型相同时, 指针变量可以指向数组或数组中的任意元素.
设: *ptr = &a[0]. 则*(ptr + i) = *(ptr地址 + i * (数据类型宽度) )
假设A首址SA在ECX,i 在EDX,结果在EAX, 数组类型为int

指针数组
- 若干指向同类目标的指针变量组成的数组
- 一般定义形式: 存储类型 数据类型 *指针数组名[元素个数]
- 一个指针数组可以实现一个二维数组

结构体
结构体成员在内存的存放和访问
- 分配在栈中的auto结构型变量的首地址由EBP或ESP来定位
- 分配在静态区的结构型变量首地址是一个确定的静态区地址
- 结构型变量 x 各成员首址可用“基址加偏移量”的寻址方式

对于字符类型变量在结构体中的存储. 自该char变量的开头开始存放, 字符结束后为\0, 之后一直到变量结束地址都是空字符.

联合体
联合体数据的分配和访问
联合体各成员共享同一存储空间, 按最大长度成员所需空间大小为准.
- C语言的联合体中不同字段的使用时间互斥. 可以减少存储空间占用.
- 也可以对相同01序列的数据进行不同数据类型的解释.(e.g. 对于某一int型变量, 直接将其视为unsigned型变量, 但不进行数据类型转换处理)
- 利用联合体内的嵌套定义链表结构
数据对齐
- 目前机器字长为32位或64位,主存按一个传送单位(32/64/128位)进行存取,而按字节编址,例如:若传送单位为64位,则每次最多读写64位,即:第07字节同时读写,第815字节同时读写,……,以此类推。主存不能跨单位同时读取, 即在64位主存中, 不能同时读取7和8字节. 按边界对齐,可使读写数据位于8i~8i+7(i=0,1,2,…) 单元
- 指令系统支持对字节、半字、字及双字的运算. 数据的长度可能跨单位, 此时需要多次访存.
各种不同长度的数据存放时,有两种处理方式:
- 按边界对齐(若一个字为32位)
- 字地址:4的倍数(低两位为0)
- 半字地址:2的倍数(低位为0)
- 字节地址:任意
不按边界对齐 - 坏处:可能会增加访存次数
对齐策略
- 按数据长度对齐
- Windows采用策略:int型地址是4的倍数,short型地址是2的倍数,double和long long型的是8的倍数,float型的是4的倍数,char不对齐
- Linux采用更宽松策略:short型是2的倍数,其他类型如int、float、double和指针等都是4的倍数
*结构数组变量的最末可能需要插空,以使每个数组元素都按4字节边界对齐

浙公网安备 33010602011771号