最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

swap()函数的4种实现

工作和技术 crifan 6768浏览 0评论

在别处看到一个,之前自己没见过的,新颖的,swap函数的实现方法,所以摘录与此,顺便总结一下,目前见过的,swap函数的几种实现方法:

1。借用临时变量实现swap

void swap1(int *a, int *b)
{
int temp;

temp = *a;
*a = *b;
*b = temp;
}
说明:
此种方法,最常见。
使用起来,虽然效率低,但是也没什么限制。

2。利用加减法实现swap

void swap2(int *a, int *b)
{
*a = *a + *b;
*b = *a – *b;
*a = *a – *b;
}
说明:
此法之前就见到,可以省去临时变量。
缺点:调用此函数之前,要保证两个数相加之和不会溢出。

3。利用异或操作的特性实现swap

void swap3(int *a, int *b)
{
#if 0
//*a ^= *b ^= *a ^= *b;
*a ^= ( *b ^= (*a ^= (*b)) );
#else
printf("In swap3:n");
*a = *a ^ *b;
printf("1: a=%d, b=%dn", *a, *b);
*b = *b ^ *a;
printf("2: a=%d, b=%dn", *a, *b);
*a = *a ^ *b;
printf("3: a=%d, b=%dn", *a, *b);
#endif
}
说明:
A 。书写上,最简介的莫过于:
*a ^= *b ^= *a ^= *b; [1]
其等价于:
*a ^= ( *b ^= (*a ^= (*b)) ); [2]
理论上,(如果编译器的规则是,对于等于号“=”赋值,是从又向左结合的话)也等价于:
*a = *a ^ *b;
*b = *b ^ *a;
*a = *a ^ *b;      [3]
B。对于上述中的[1]或[2]
我在用gcc编译的时候,遇到一个觉得很奇怪的现象。
如果是直接编译,不加其他参数的话:
gcc -o swapFunc   swap.c
运行的结果,[1]和[2],均错误,好像是a必然是0,b好像是swap掉换过来了。
而如果加上优化参数 -ON 其中N只要>1,比如2,3,。。均可。
运行结果就正常,就可以实现swap功能。
很纳闷,觉得按理来说,应该是加了优化参数,有可能会导致程序运行出错,而不加优化参数,
程序运行应该正确才对,而此处正好相反。
无语。。。期待哪位知道原因的,给解释一下。
注,此处测试平台是Ubuntu 9.04,gcc 是:
crifan@ubuntu904:~$ gcc -v
使用内建 specs。
目标:i486-linux-gnu
配置为:../src/configure -v –with-pkgversion=’Ubuntu 4.3.3-5ubuntu4′ –with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs –enable-languages=c,c++,fortran,objc,obj-c++ –prefix=/usr –enable-shared –with-system-zlib –libexecdir=/usr/lib –without-included-gettext –enable-threads=posix –enable-nls –with-gxx-include-dir=/usr/include/c++/4.3 –program-suffix=-4.3 –enable-clocale=gnu –enable-libstdcxx-debug –enable-objc-gc –enable-mpfr –enable-targets=all –with-tune=generic –enable-checking=release –build=i486-linux-gnu –host=i486-linux-gnu –target=i486-linux-gnu
线程模型:posix
gcc 版本 4.3.3 (Ubuntu 4.3.3-5ubuntu4)
另外,无论如何编译,[3]都是可以正常实现swap的功能的,这个在情理之中。

上面现象的运行结果如下:

crifan@ubuntu904:swapFunc$ gcc -o swapFunc   swap.c
crifan@ubuntu904:swapFunc$ ./swapFunc

Test value: a=40, b=-300
After call swap1: a=-300, b=40

Test value: a=-300, b=40
After call swap2: a=40, b=-300

Test value: a=40, b=-300
After call swap3: a=0, b=40

Test value: a=0, b=40
浮点数异常
crifan@ubuntu904:swapFunc$ gcc -o swapFunc -O1 swap.c
crifan@ubuntu904:swapFunc$ ./swapFunc

Test value: a=40, b=-300
After call swap1: a=-300, b=40

Test value: a=-300, b=40
After call swap2: a=40, b=-300

Test value: a=40, b=-300
After call swap3: a=-300, b=40

Test value: a=-300, b=40
After call swap4: a=40, b=-300
crifan@ubuntu904:swapFunc$

C。此种实现方法,效果相对最好,不需要借助临时变量,而且不用考虑溢出,被0除等情况。

4。利用乘除操作实现swap
void swap4(int *a, int *b)
{
/* makesure b != 0 */
assert(b!=0);

*a = (*a) * (*b);
*b = (*a) / (*b);
*a = (*a) / (*b);
}
说明:
同方法2,只是换个预算规则而已,从加减换到乘除。
缺点也是,此处出了要保证*a X *b 没有溢出之外,还要保证*b不能为0,而且*a也不能为0,否则也不能实现swap功能。

[测试源码]
/*
* Demo several realization of swap() function.
*
* by [email protected]
*/

#include <stdio.h>
#include <assert.h>

void swap1(int *a, int *b)
{
int temp;

temp = *a;
*a = *b;
*b = temp;
}

void swap2(int *a, int *b)
{
*a = *a + *b;
*b = *a – *b;
*a = *a – *b;
}

void swap3(int *a, int *b)
{
#if 1
//*a ^= *b ^= *a ^= *b;
*a ^= ( *b ^= (*a ^= (*b)) );
#else
printf("In swap3:n");
*a = *a ^ *b;
printf("1: a=%d, b=%dn", *a, *b);
*b = *b ^ *a;
printf("2: a=%d, b=%dn", *a, *b);
*a = *a ^ *b;
printf("3: a=%d, b=%dn", *a, *b);
#endif
}

void swap4(int *a, int *b)
{
/* makesure b != 0 */
assert(b!=0);

*a = (*a) * (*b);
*b = (*a) / (*b);
*a = (*a) / (*b);
}

int main(void)
{
// int a=1, b=200;
int a=40, b=-300;

printf("nTest value: a=%d, b=%dn", a, b);
swap1(&a, &b);
printf("After call swap1: a=%d, b=%dn", a, b);

printf("nTest value: a=%d, b=%dn", a, b);
swap2(&a, &b);
printf("After call swap2: a=%d, b=%dn", a, b);

printf("nTest value: a=%d, b=%dn", a, b);
swap3(&a, &b);
printf("After call swap3: a=%d, b=%dn", a, b);

printf("nTest value: a=%d, b=%dn", a, b);
swap4(&a, &b);
printf("After call swap4: a=%d, b=%dn", a, b);

return 0;
}

转载请注明:在路上 » swap()函数的4种实现

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (2)

  1. 回复renyaob:3q
    againinput415年前 (2009-10-04)回复
  2. 3。利用抑或操作的特性实现swap-----异或
    renyaob15年前 (2009-10-04)回复
82 queries in 0.196 seconds, using 22.10MB memory