关于变量互换效率的探讨

关于变量交换效率的探讨
本帖最后由 guoguo1127 于 2015-11-07 20:34:30 编辑
本人刚刚开始学习C语言不久,有一些想法向大神们请教。
        我们知道,在C语言中函数形参总是实参的复制,因此如果想用函数来实现两个数的交换,则需要使用指针(或者引用,引用在c++中才可以用,这里不予讨论)。
         那么,实现数值交换至少有两种方法:1.通过指针交换两个变量内存中的数据。2.通过指针的指针(暂称为二元指针)来改变指针的指向实现简介的交换,简单来说就是:
第一种方法:

  1 int swap(int* pa,int* pb)
  2 {
  3         int tmp;
  4         tmp=*pa;
  5         *pa=*pb;
  6         *pb=tmp;
  7 }

第二种方法:

  1 int swap(int** pa,int** pb)
  2 {
  3         int* tmp;
  4         tmp=*pa;
  5         *pa=*pb;
  6         *pb=tmp;
  7 }

        我个人直观上认为,通过改变指针的指向不一定比替换对应内存中的数据要快。因为:假设指针变量占用4个字节的内存(实际上在我电脑上确实是这样),而除了double或者自己定义的类型外,int,float,char的存储空间都要小于4个字节。指针变量本质上也是一种变量,改变指针的指向实际上是改变指针变量存储的数值,也就是需要替换4个字节,因此原则上,对于int等长度少于4字节的变量,改变指针指向的方法来实现变量交换效率反而相对较低:但是实验结果却不是这样,如下:

 1 #include<stdio.h>
  2 #include<time.h>
  3 int main()
  4 {
  5         time_t bg,ed;
  6         int a=10,b=20,i;
  7         int* pa,*pb;
  8         pa=&a;pb=&b;
  9         void uswap(int *pa,int*pb )
 10         {
 11                 int tmp;
 12                 tmp=*pa;
 13                 *pa=*pb;
 14                 *pb=tmp;
 15         }
 16         void uswap2(int **pa, int**pb)
 17         {
 18                 int *pptmp;
 19                 pptmp=*pa;
 20                 *pa=*pb;
 21                 *pb=pptmp;
 22         }
 23         bg=clock();
 24         for(i=0;i<20000;i++)
 25         {
 26                 uswap(pa,pb);
 27         }
 28         ed=clock()-bg;
 29         printf("对换存储位置的互换时间平均为:%fms\n",(double)ed*1000/CLOCKS_PER_SEC);
 30         bg=clock();
 31         for(i=0;i<20000;i++)
 32         {
 33                 uswap2(&pa,&pb);
 34         }
 35         ed=clock()-bg;
 36         printf("对换存储位置的互换时间平均为:%fms\n",(double)ed*1000/CLOCKS_PER_SEC);
 37 }

输出结果如下:
对换存储位置的互换时间平均为:0.479000ms
对换存储位置的互换时间平均为:0.428000ms
可见,对于4字节的变量,通过改变指针指向的方式效率还是相对要高(这里,int*和int都占用4字节)。
但是对于double形来说:
对换存储位置的互换时间平均为:0.504000ms
对换存储位置的互换时间平均为:0.463000ms
采用替换指针指向的方式效率更是提高了。
那么,替换指针指向的原理到底是什么?难道不是替换指针变量的值么?改变指针变量值不需要4个字节的替换?

此外,网上通常说,位运算要相对比代数运算效率高,因此这里夜做了实验:
  1 #include<stdio.h>
  2 #include<time.h>
  3 int main()
  4 {
  5         time_t bg,ed;
  6         int a=10,b=20,i;
  7         int* pa,*pb;
  8         pa=&a;pb=&b;
  9         void uswap(int *pa,int*pb )
 10         {
 11                 int tmp;
 12                 tmp=*pa;
 13                 *pa=*pb;
 14                 *pb=tmp;
 15         }
 16         void uswap2(int *pa, int*pb)
 17         {
 18                 *pa^=*pb;
 19                 *pb^=*pa;
 20                 *pa^=*pb;
 21         }
 22         bg=clock();
 23         for(i=0;i<20000000;i++)
 24         {
 25                 uswap(pa,pb);
 26         }
 27         ed=clock()-bg;
 28         printf("互换时间平均为:%fms\n",(double)ed*1000/CLOCKS_PER_SEC);
 29         bg=clock();
 30         for(i=0;i<20000000;i++)
 31         {
 32                 uswap2(pa,pb);
 33         }
 34         ed=clock()-bg;
 35         printf("互换时间平均为:%fms\n",(double)ed*1000/CLOCKS_PER_SEC);
 36 }

输出结果为:
互换时间平均为:183.542000ms
互换时间平均为:248.888000ms
所以,位运算虽然使代码简介,并不必引入新的变量,但是其效率并不会提高,对么?
------解决思路----------------------
不是变量类型字节越少越快!! 32位下一次读写是4个字节
在MFC里一般都用BOOL(其实就是int)来代替bool就是为了效率更高

另外如果再送楼主2种交换a与b的方法;

方法一:
    a=a+b;
    b=a-b;
    a=a-b;

方法二:
a=a^b; 
b=a^b; 
a=a^b;

如果你不想用引用传入函数,那你就用指针操作用上面两种方法也行