码迷,mamicode.com
首页 > 编程语言 > 详细

数组分配与访问

时间:2019-10-13 13:22:55      阅读:93      评论:0      收藏:0      [点我收藏+]

标签:内存   height   def   回顾   有一个   基本   等于   编译   空间   

数组:将标量数据聚集成更大数据类型

C语言实现数组简单,容易翻译成机器代码

在机器代码中,这些指向数组元素的指针会被翻译成地址计算

优化编译器非常善于简化数组索引所使用的地址计算,这使得我们难以理解C语言代码与机器代码的对应关系

 

一. 基本原则

一维数组的声明:T A[N](T为数据类型,N为常数)

两个效果:在内存中分配L*N字节的连续区域;引入标识符A,用A来作为指向数组开头的指针,值为xA

数组元素i会存放在xA+i*L的地方

内存引用指令可以用来简化数组访问

movl (%rdx, %rcx, 4), %eax 执行地址计算xA+4i,并将结果存放在寄存器%eax中

伸缩因子1, 2, 4, 8覆盖了所有数据类型的大小

知识点回顾

内存引用是操作数的一种

操作数一共有3种:

  1. 立即数(书写方式:‘$’后面跟一个用标准C表示法表示的整数,例如$-577,$0x1F)、
  2. 寄存器(书写方式为寄存器的名称ra,实际上操作的是寄存器里的值R[ra],将寄存器集合看成一个数组R,用寄存器标识符作为索引)、
  3. 内存引用(根据计算出来的地址Addr访问某个内存位置Mb[Addr],表示对存储在内存中地址Addr开始的b个字节值的引用)
    1. 计算地址的方式称为寻址模式,具体形式为:Imm(rb, ri, s) Imm表示一个立即数,rb称为基址寄存器,ri称为变址寄存器,s称为比例因子(s属于{1, 2, 4, 8}
    2. 计算公式:Imm+R[rb]+R[ri]*s

技术图片

 

 

二. 指针运算

C语言允许对指针进行运算,计算出来的值会根据该指针引用的数据类型的大小进行伸缩,例如表达式p+i的值为xp+L*i

技术图片

表达式2, 3, 6返回数组值,类型为数组元素的类型int,因此涉及4字节操作,例如指令movl和寄存器%eax

表达式1, 4, 5返回指针,类型为int*,因此涉及8字节操作,例如指令leaq和寄存器%rax

注意??:表达式7可以计算同一个数据结构中的两个指针之差,结果的数据类型为long,值等于两个地址之差除以该数据类型的大小

 

三. 嵌套的数组

声明一个二维数组A

int A[5][3];//直接声明
等价于
typedef int row3_t[3];//嵌套声明
row3_t A[5];//可以立即为用A[5]去替换int row3_t[3]中的row3_t

这一部分的重点只有一个: 

声明数组:T D[R][C];

则它的元素D[i][j]的内存地址为&D[i][j]=xD+L(C*i+j),L为数据类型T的大小

用行优先索引将多维数组映射到一维数组

考法:运用逆向工程,根据汇编代码确定R和C的值

 

四. 定长数组

定长数组的声明

#define N 16
typedef int fix_matrix[N][N];//将fix_matrix声明为16*16的整形数组

这部分主要讲了C语言编译器对定长多维数组的优化

例如计算两矩阵乘积的某一个元素,编译器会优化掉for循环所用的循环变量i,转换为指针的计算,左矩阵Aptr++,右矩阵Bptr+=N,并将for循环变为do-while循环,直到Bptr指向矩阵外时停止

例如将一矩阵的对角线上的元素赋值为val,编译器会优化掉for循环所用的循环变量i,转换为指针的计算,每次ptr+=N+1,并将for循环变为do-while循环,直到ptr指向矩阵外时停止

 

五. 变长数组

在历史上,C语言只支持大小在编译时就能确定的多维数组(对第一维有些例外)。那时候,程序员需要变长数组时不得不用malloc、calloc等函数为数组分配存储空间,并且需要程序员自己讲多维数组映射到一维数组,写入C语言程序。

ISO C99引入功能:数组的维度可以是表达式,在数组被分配的时候被计算出来

与定长数组的区别在于:必须用乘法指令imulq对i伸缩n倍,不能用一系列的移位和加法

利用访问模式的规律性来优化索引的计算

回到刚才的例子,计算两矩阵乘积的某一个元素,识别出访问数组元素的步长,生成的代码会避免直接使用内存地址公式的乘法计算(由于乘法计算较耗时,因此少去一步乘法计算会显著提高程序性能)

 

数组分配与访问

标签:内存   height   def   回顾   有一个   基本   等于   编译   空间   

原文地址:https://www.cnblogs.com/louisekou666/p/11665820.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!