回家的效率明显下降了,但是第三章还是快要结束的节奏。今天看到定长数组这里的时候,看到一个好玩的东西。在计算机的底层中,所有对数组的操作都是利用指针来完成的。数组其实也是一个很简单的数据结构,就是把一些最简单的数据类型合并在一段连续的内存区域上,这就是一个复合类型---数组。
学C语言的时候,大家都知道访问数组元素有两种方法,一种是利用数组名加索引的形式,另外一种就是利用指针加上偏移量的形式。在底层中,不管你用什么方式来访问元素,最后多会转化成对指针的操作。
在编写 代码的时候,编译器在编译过程中会对代码进行一定的优化。
今天碰到的一个问题就是按照一个例子,给一个把16*16的二维数组的对角线元素都设定为val值的C语言代码,让你根据编译器的优化规则写一个份优化过的C语言代码,具体的例子还是给大家贴一下图吧,不然看着前后搭不上。
编译器还是挺聪明的不是么,看看两种代码的区别就知道编译器做了什么工作了。
我的理解就是,优化还是在于对指针还是偏移量的运算这里。
所以,根据上面的那个任务,我写了一个版本如下。
在贴代码之前我要说的是,每一层的对角线的元素都和他临近的对角线元素差n+1个元素,这个n是二维数组的列数。
int *p = &A[0][0] for(int i = 0; i < n*(n + 1); i = i + n+1) p[i] = val
这个代码模仿起来写很容易,但是之后你仔细一想,还是挺有意思的。编译器是把原来对二维数组的操作,变为对一维数组进行操作,因为我一开始把p指针指向的是一个一维数组里面的一个元素。也就是说,现在整个二维数组都看成了一个一维数组,只不过这个一维数组在我们看来是拐着弯排列的。其实在内存中,二维数组中的每一个元素都是一个地址,这个地址就是二维数组内一维数组的首地址。大家在物理上都是相邻的。
所以这样这份代码就很好解释了。利用指针和便宜量的运算,把整个二维数组内的所有元素看成是一个一维数组,这样一来,只要找到增量的规律就可以完成了。
另外还要说的就是这个循环条件,因为我是从0开始进行循环的,所以说数组的维度是n,所以最多只能到(n-1)(n+1)