为什么C语言中不能通过指针变量的交换来完成指针变量所指向的数据的交换?

    本人学生,在完成作业时遇到这个问题:输入三个整数,按由小到大的顺序输出。并且要求使用指针,于是我写了这样的代码

#include<stdio.h>
void swap(int *a,int *b, int *c)
{
    int *i;
    if(*b>*a)
        i=a;
        a=b;
        b=i;
    if(*c>*a)
        i=a;
        a=c;
        c=i;
     if(*c>*b)
         i=b;
        b=c;
        c=i;
}
int main()
{
    int q,w,e;
    int *a,*b,*c;
    scanf("%d,%d,%d",&q,&w,&e);
    a=&q;
    b=&w;
    c=&e;
    swap(a,b,c);
    q=*a;
    w=*b;
    e=*c;
    printf("%d,%d,%d",*a,*b,*c);
    return 0;
}
然而,却行不通,这是为什么?

唉,这上面都没说到点上,让我来给你醍醐灌顶吧

1. 你这个swap函数交换的是参数里指针的指向,此函数运行完,参数指针就释放了。这相当于你做了交换,然后放弃了结果。

2. 为啥在swap中不改指针指向,直接改数值就,其结果可以保存下来?

因为你的变量是在main中定义的,其内存的销毁需要在main才会进行,所以你传指针到swap中,利用指针交换他们的值,值保存在指定的内存中,swap结束,内存没释放,这就保存下来了。

3. 你可能有个误区,认为只要用指针做参数就可以保留修改结果,这个想法是不准确的,用指针传递时,需要对其内容修改,才能保存结果。

“指针”和“指针指向的变量”是**完完全全的两码事**。你这样只操作了指针,却没有改变所指向地址的内容,肯定是不行的。

打个比方:这个问题就相当于有张三、李四、王五三个人从左到右依次站成了一排,要按个子排序。这三个人就是变量,“张三”“李四”“王五”是三个指针,指向三个实际的人。假设张三1米7,李四1米6,王五1米8,要交换张三和李四的位置,他们的名字在其中起了什么作用呢?仅仅是告诉你“要交换张三和李四的位置”而已。你所做的交换指针的值,本质上就是把张三和李四两个名字互换了(改变了指向的具体位置),却没有改变这两个人的站位。相当于原来叫张三的人被你改叫李四,原来叫李四的人被你改叫张三。表面上的确变成了李四、张三、王五的顺序,问题是现在的李四仍然是原来的张三,他们三个仍然是1米7、1米6、1米8的顺序,没有完成排序的任务。

一言以蔽之:你改变指针的值的组织结构,对于指针所指向变量的内容不会有丝毫的影响。题目要求的是“交换指针指向变量的值”,你做的是“交换指针的值”,这两件事完全不是一码事。

改了下程序,貌似可以达到目的了,你自己去研究吧。

#include<stdio.h>
int *a1,*b1,*c1;
void swap(int *a,int *b, int *c)
{
    int *i;
    if(*b>*a)
    {
        i=a;
        a=b;
        b=i;
        printf("%d,%d,%d,%d\n",*a,*b,*c,*i);
    }
    if(*c>*a)
    {
        i=a;
        a=c;
        c=i;
        printf("%d,%d,%d,%d\n",*a,*b,*c,*i);
    }
     if(*c>*b)
     {
         i=b;
        b=c;
        c=i;
        printf("%d,%d,%d,%d\n",*a,*b,*c,*i);
     }
     a1=a;
     b1=b;
     c1=c;
}
int main()
{
    int q,w,e;
    scanf("%d,%d,%d",&q,&w,&e);
    a1=&q;
    b1=&w;
    c1=&e;
    swap(a1,b1,c1);
    printf("%d,%d,%d",*a1,*b1,*c1);
    return 0;
}

 

//输入三个整数,按由小到大的顺序输出。并且要求使用指针
#include <stdio.h>
void swap01(int* a, int* b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}
void swap(int* a,int* b,int* c)
{
    if (*a > *b)
    {
        swap01(a, b);
        if (*a > *c)
            swap01(a, c);
        if (*b > *c)
            swap01(b, c);
    }
    else
    {
        if (*b > *c)
            swap01(b, c);
        if (*a > *c)
            swap01(a, c);
    }
}

int main()
{
    int a, b, c;
    scanf_s("%d %d %d", &a, &b, &c);
    swap(&a, &b, &c);  //地址传递,改变的是a,b,c中地址所指向的值
    //swap(a,b,c)         值传递,函数中的形参是实参的副本
    printf("%d\t%d\t%d\t", a, b, c);
    return 0;
}

我简单的说一下我对指针的理解,首先,指针就是地址,这是理解指针最关键的!main函数中定义的a,b,c都是变量,如果想改变变量中的值,就需要传参时传递变量的地址,函数参数中int* a,int*表明这是一个指针变量a,这个a和main函数中的a指向一个地址,所以可以直接修改其中的值。*a是解引用,表明取a指向地址的值。

void main()
{
int a=3;
int b=4;
printf("a=%d,b=%d",a,b);

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

printf("a=%d,b=%d",a,b);

}