tiger1125 发表于 2010-1-31 19:03:44

二维数组遍历:下标法与指针法的较量

在图像的采集中,常常需要用到二维数组,这里数组的遍历是指按照一定的顺序访问数组中所有的元素。

在众多的遍历方法中,下标法和指针法是两种常用的方法。但在使用的时候,我们只需要选择其中的一种,那么如何选择呢?

相信很多人都会脱口而出:当然是指针法快啦!但实际上真的如此吗?下面我会用实验说明什么才是最快的。

由于这次面向的对象是freescale的单片机,所以编译用的IDE是Codewarrior for HCS12(X) V5.0。

为这两种方法各建立一个工程,对同样的二维数组进行遍历,然后用Hiwave Ture-Time Simulation进行仿真,分别记录下各自的执行的总时间。Hiwave中CPU执行的时间用时钟周期表示,时间越少效率越高。

好的,废话少说,开始验证……



下标法的源代码:

#include <hidef.h>   
#include "derivative.h"   

#include <stdio.h>


uchar temp;


void main(void) {

uchar a=
{
{1,3,5,7},
{9,11,13,15},
{17,19,21,23}
};
uchar i,j;
for(i=0;i<3;i++)
    for(j=0;j<4;j++)
      temp=a;
for(;;) {
    _FEED_COP();
}

}



编译通过后,进入仿真模式,在 _FEED_COP()这里设置一个断点,这样我们可以看到前面所有程序运行的总的时钟周期。

运行后的界面如下:


http://cache.amobbs.com/bbs_upload782111/files_25/ourdev_531215.JPG
(原文件名:array_index.JPG)



看到任务栏的时钟周期了吧,473个Cycle。

也就是说,程序从开始执行到断点处,一共用了473个时钟周期。



接下来,我们测试一下指针法。



指针法程序代码:

#include <hidef.h>   
#include "derivative.h"   

#include <stdio.h>


uchar temp;


void main(void) {



uchar a=
{
{1,3,5,7},
{9,11,13,15},
{17,19,21,23}
};
uchar i,j;
uchar (*p)=a;
for(i=0;i<3;i++)
    for(j=0;j<4;j++)
      temp=*(*(p+i)+j);

for(;;) {
    _FEED_COP();
}

}


从上面的程序可以看出,我们的程序执行的功能是一样的,只不过是用了另一种方法而已,

同样也是在_FEED_COP()这里设置一个断点,运行仿真,来一张截图:

http://cache.amobbs.com/bbs_upload782111/files_25/ourdev_531216.JPG
(原文件名:array_point.JPG)



从任务栏的信息看出,执行到断点处一共用了477个Cycle。

结果摆在眼前,比起下标法多用了4个Cycle,可见是下标法更具效率



后记:

开始的时候,我也像很多人一样,在直觉上觉得指针法肯定比下标法要快,但是,对于不同架构的CPU,内存寻址的方法不一样,编译器对于用C语言指针生成的代码的实现方法也有各自的特色,对应的执行效率也不一样。



希望通过这一个小测试,能够引起大家的注意,对于没有把握的问题,不能想当然的认为,最直接的手段是通过试验来说明问题,而不是一味的猜想,这样是永远得不到正确的答案的。

tomhe666 发表于 2010-1-31 19:23:43

这个,你这指针法写的明显不够优化,我觉得应该如下写再去比较谁快谁慢
for(unsgiend long I = 0; I<i*j; I++)
{
   temp = *p++;
}
(其中i,j为你的二维数组下标)

shark 发表于 2010-1-31 20:04:46

较量啥呀,都说100遍了, a和 *(a+i) 完全等价, a和*( *(a+i)+j) 完全等价。

指针运算只有在自加(减)的时候才可能快 。
页: [1]
查看完整版本: 二维数组遍历:下标法与指针法的较量