温故而知新:C语言中swap函数

最近在学习数据结构和算法,发现使用到swap()函数,于是重新看了一下swap函数的各种实现,发现我对函数实参和形参理解不够透彻,现在分享我对swap的一些见解。

我们通常使用以下一段代码来实现整型变量的交换:

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

而以下两种是不能实现交换的:

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

对于swap1,不能实现交换的理由是,C语言中函数的传的是形参,也就是一个副本,虽然在函数内体内交换了,但对真实的数据没影响。就如以下代码:

{
     int a=1,b=2;
     int ta=a,tb=b;
     int temp;
     temp=ta;
     ta=tb;
     tb=temp;
}

a和b并没有因此交换,交换的只是编译器自动生成的临时变量ta(形参)和tb!

而对于swap2,执行过程如下代码:

{
	int a=1,b=2;
	int *ta=&a,*tb=&b;
	int *temp;
	temp=ta;
	ta=tb;
	tb=temp;
}
printf("a=%d,b=%d",a,b);

pirintf("a'=%d,b'=%d\n",*ta,*tb);可以看到交换了由副本指向的内容,但a,b内容不会变,即原本是ta指向a(ta = &a),tb指向b(tb = &b),交换后,变为ta指向b(ta = &b),tb指向a(tb = &a),相当于换一个指针变量指向a、b的地址,对a和b的值并无影响。

void swap3(char **a,char**b)
{
	char *temp;
	temp=*b;
	*b=*a;
	*a=temp;
}

//使用如下方式调用:
char *pa=&a,*pb=&b;
swap1(&pa,&pb);

调用前和调用后分别打印printf("a=%d,b=%d,a'=%x,b'=%x\n",a,b,&a,&b);可以看到:并没有交换a和b由编译器分配的地址,交换的是指针pa和pb的值,所以a和b的值还是没变。其实跟上面的swap2()函数很类似,不同的是swap2()交换的是由编译器为实现函数形参功能而隐式生成的临时指针变量ta和tb,swap3函数则是交换调用swap3前显式定义好的指针变量pa和pb。

 

最后关于C语言的泛型编程,上面的swap()只能处理整型变量,但我们需要同时可以处理char、double、long型的变量,我们可以使用void*和size_t这些类型来达到。如下

void swap(void *a,void *b,size_t size)
{
    char *p1=(char *)a;  
    char *p2=(char *)b;
    char temp;      
    while(size--)
    {
        temp=*p1;
        *p1=*p2;
        *p2=temp;
        p1++;
        p2++;
    }
}

 

使用这样的形式调用:

int c = 1000;
int d = -18;
swap(&c,&d,sizeof(int));
或
float a = -4.6;
float b = -2.1;
swap(&a,&b,sizeof(float));
等

但要注意的是彼此之间应该是同种类型,否则会出现错误的结果或内存越界。


 

 

  • 79
    点赞
  • 295
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值