swap函数估计是一个各种各样程序都会频繁用到的子程序,可是你知道它究竟有多少种不同的写法吗?下面我就列举我知道的几种swap函数来跟大家分享一下。

(1)经典型---嫁衣法

无论是写程序还是干其他事情,一旦涉及到交换,就总是会遇到第三方。这个第三方可能是公正的监督者,也可能是一个徒为他人做嫁衣的可怜虫。在经典法的交换程序中,我们就需要有一个可怜虫来为我们提供暂时的服务。程序如下:

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

temp=*a;

*a=*b;

*b=temp;

}

我们看到,我必须用一个temp变量作为过渡,让他先拥有然后又再赋值给其他人。可见他也不是徒做嫁衣,而是先索取后奉献的主人公精神。哈哈,扯远了。

(2)经典型改进版---范型法
上面的那个swap函数只能交换int类型变量,如果我想交换double类型,short类型,char类型......呢?上面的程序就必须重新写,可是又不是完全推倒重来,只需要修改相应的类型变量就可以了,如果是用C++来编程,我们还可以用到NB的模板,可是C语言就没有这种特点了。唯一可以用的便是void*指针。void*指针可以视为一种通用指针,任何指针都可以转换为void*指针而不会丢失值。同理,只要我们把原先的指针变量换成void*类型不就行了。可是,你很快发现,这样不行。为什么呢?因为我们没有通用的嫁衣。C语言中的变量不可以为void类型,也就是说没有void temp; 这种古怪的东西。那怎么办呢?我们可以从底层去想两个数交换的本质。不就是相应的内存值交换嘛。我们可以联想到memcpy函数,我们可以模仿着来,写一个函数,通过传入void*指针和变量类型的字节大小,来将这两个变量相应的字节内容发生对换。程序如下:

void swap(void *a,void *b,size_t size)
{

unsigned char *p1=(unsigned char *)a;          //强制类型转换

unsigned char *p2=(unsigned char *)b;

Unsigned char temp;                         //字节型的嫁衣

while(size--)

{

temp=*p1;

*p1=*p2;

*p2=temp;

p1++;

p2++;

}

}

使用的时候可以这样调用:swap( &a,&b,sizeof(int) );
这种字节的分别交换可以通用各种类型的交换,当然,彼此之间应该是同种类型,否则会因为类型大小,字节序等一些问题发生错误。

(3)取巧型---赋值法
这个方法其实一个很取巧的方法,大家先看一下程序,看能不能看出巧在哪里:
void swap(int *a,int *b)
{
*a=*a+*b;

*b=*a-*b;

*a=*a-*b;

}
这种方法有一个好处,那就是不用消耗额外的变量空间,只需要两个变量做一些运算即可。让我们慢慢看:
首先:

我用A代表a+b

A=a+b,            这时候A的值为两者之和

接着,b=A-b, 也就是b=A-b=a+b-b=a,这时候b得到了a的值
最后,a=A-b, 因为经过上面的运算,b=a,所以a=A-b=a+b-a=b,这时候a得到了b的值。
所以,交换成功了。

(4)诡异型---逻辑运算法
如果没有仔细拿纸算一算的话,这段程序估计会晕倒很多人,让我们来看一下吧:
void swap(int *a,int *b)
{

//  *a^=*b^=*a^=*b;  这种做法达不到效果,不知道为什么

*a=*a^*b;
*b=*b^*a;
*a=*a^*b;

}
怎么样,够诡异的吧。如果我们把它拆开来看的话,其实也没那么可怕:
首先我们必须明确运算顺序,是从右至左:
*a=*a^*b;
*b=*b^*a;
*a=*a^*b;
在解释这段代码的时候,我们先普及一下逻辑运算的基础知识,^ 符号是异或符号,也就是如果两个逻辑变量各不相同,其表达式值为1,反之为0 。则有:

A^A=0

A^1=~A
A^0=A
A^B^C=A^(B^C)=B^(A^C)

首先,A=a^b;

接着,b=b^A=b^a^b=a^0=a,这时候b获得了a的值。
最后,a=A^b=a^b^a=b^0=b,这时候a获得了b的值。

@清晰掉 swap函数的更多相关文章

  1. 从Swap函数谈加法溢出问题

    1.      初始题目 面试题:). 这个题目太经典,也太简单,有很多人都会不假思索结出答案: //Code 1 void Swap(int* a, int* b) { *a = *a + *b; ...

  2. 关于swap函数传值的问题

    #include <stdio.h> void swap(int * p3,int * p4); int main() {  int a = 9;  int b = 8;  int * p ...

  3. 自己写一个swap函数交换任意两个相同类型元素的值 对空指针的使用 字节大小的判断(二)了解原理

    验证的代码: #include <stdio.h> int main(){ char c = 'z'; ) + (c << ) + () + 'a'; printf(" ...

  4. swap函数的四种写法

    swap 函数的四种写法 (1)经典型 --- 嫁衣法 void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } ( ...

  5. c++ swap 函数

    转载地址 1,最通用的模板交换函数模式:创建临时对象,调用对象的赋值操作符. template <class T> void swap ( T& a, T& b ) { T ...

  6. [转]谈谈C++中的swap函数

    1,最通用的模板交换函数模式:创建临时对象,调用对象的赋值操作符. template <class T> void swap ( T& a, T& b ) { T c(a) ...

  7. [Effective C++ --025]考虑写出一个不抛异常的swap函数

    引言 在我的上一篇博客中,讲述了swap函数. 原本swap只是STL的一部分,而后成为异常安全性编程的脊柱,以及用来处理自我赋值可能性. 一.swap函数 标准库的swap函数如下: namespa ...

  8. [020]转--C++ swap函数

    原文来自:http://www.cnblogs.com/xloogson/p/3360847.html 1.C++最通用的模板交换函数模式:创建临时对象,调用对象的赋值操作符 template < ...

  9. EC读书笔记系列之13:条款25 考虑写出一个不抛异常的swap函数

    记住: ★当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定其不抛出异常 ★若你提供一个member swap,也该提供一个non-member swap来调用前者.对于cla ...

随机推荐

  1. 在Vue项目中加载krpano全景图

    在Vue-cli项目中做krpano全景图编辑器的时候,由于js插件的路径是动态的,做的过程中遇到了加载不到资源的难题,在网上搜索了好久也没找到合适的办法,最后想到了可能是JS加载的问题,于是解决了问 ...

  2. Jpa/Hibernate 字节码增强:字段延迟加载

    JPA提供了@Basic注解,实现延迟加载字段的功能,如下: @Basic(fetch = FetchType.LAZY) @Column(name = "REMARK_CONTENT&qu ...

  3. PHP之面试题总结

    总结一些面试题,有备无患,走起... 1.熟悉的 nosql 和 sql 有什么区别(优势,劣势) Memcache,Redis 都是内存数据库 redis是一个开源的支持多种数据类型的key=> ...

  4. $id(id)函数

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. Jmeter线程组间传递参数

    现在做测试和以前不太一样了,以前只要站在一个用户的角度做端到端的UI测试就可以了,现在不会做接口测试,出去都不好意思和别人打招呼.那提到接口测试,就不得不提一下接口测试利器Jmeter,大家也都知道, ...

  6. 牛客练习赛26 D xor序列 (线性基)

    链接:https://ac.nowcoder.com/acm/contest/180/D 来源:牛客网 xor序列 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他 ...

  7. 四、Ubuntu16.04下TestLink的部署【测试管理必备工具】

    TestLink部署和使用方法 TestLink是一个基于Web的开源测试和需求管理工具.该应用程序提供测试规范.测试计划和执行,报告,需求规范以及与知名的bug跟踪器协作. 特征 l 需求管理 - ...

  8. 由n个已按1,2,3,.....,n编号的人围成一圈,从编号为1的人开始按1,2,3顺序循环报数,凡报到3者出圈,最后留一个人,问其编号是多少

    /************************************************************************* > File Name: only_one. ...

  9. Lock的await/singal 和 Object的wait/notify 的区别(转载)

    在使用Lock之前,我们都使用Object 的wait和notify实现同步的.举例来说,一个producer和consumer,consumer发现没有东西了,等待,producer生成东西了,唤醒 ...

  10. MySQL中添加、修改、删除约束

    https://blog.csdn.net/dz77dz/article/details/82119000 主要包含的约束: 非空.唯一.check.not null.默认值.主键.外键