悠幽我心 发表于 2020-9-6 19:50:42

C语言址传递

小白来请教啦?我想问的是swap函数内不是经过了地址交换了吗?为什么main函数里面第二个printf函数的输出结果还是和第一个printf函数输出一样呢,这里第二个printf函数的变量为*p1,*p2。。(为了图方便,我这里设定a=4,b=5)!

代码如下:

#include <stdio.h>

int main()
{
        void swap(int *p1,int *p2);
        int *p1,*p2,a,b;
       a = 4;b = 5;   
       p1 = &a;
       p2 = &b;
       if(a<b)
       {
                swap(p1,p2);
       }
       printf("a=%d,b=%d\n",a,b);
       printf("max = %d,min = %d",*p1,*p2);
       return 0;
}

void swap(int *p1,int *p2)
{
        int *p; p = p1; p1 = p2;p2 = p;
}

运行结果如下:
a=4,b=5
max = 4,min = 5
(我用的是devc++编译器!)

巴巴鲁 发表于 2020-9-6 19:59:56

你这样交换的是两个数的值,在swap后就被释放了
如果想进行地址传递void swap(int *p1,int *p2)
{
                int p;
                p = *p1;
                *p1 = *p2;
                *p2 = p;
}

悠幽我心 发表于 2020-9-6 20:45:11

巴巴鲁 发表于 2020-9-6 19:59
你这样交换的是两个数的值,在swap后就被释放了
如果想进行地址传递

你这种方法我知道呀,就是你看我的swap函数,里面确实是地址之间的赋值呀

巴巴鲁 发表于 2020-9-6 21:01:26

悠幽我心 发表于 2020-9-6 20:45
你这种方法我知道呀,就是你看我的swap函数,里面确实是地址之间的赋值呀

你的是值传递,*p可以看成取地址,即为一个数,所以你的程序是两个数交换了一下
我也不太知道怎么解释,表达不出来看看这篇文章,希望对你有帮助:https://blog.csdn.net/ThereIsNoCode/article/details/77996799

4goodworld 发表于 2020-9-6 22:27:12

比较正确的swap方法是这样子的
void swap(int *a,int *b)
{
    int temp;
    temp=*a;
    *a=*b;
    *b=temp;
}
这个如何形象的理解,a房子里面有一个大数,b房子里面有一个小数,你是通过a房子的门牌号找到了a然后打开门取出了大数,然后通过b房子的门牌号(指针的意思)找到了b然后打开门取了小数,同时把大数放进了b,关门,去了a房子,把小数放进去,然后再关门。这时候,a房子里面是小数,而b房子是大数,实现了交换
再看你的代码
void swap(int *p1,int *p2)
{
      int *p; p = p1; p1 = p2;p2 = p;
}
你考虑过函数的参数是如何作用的呢?
你这个代码与
void swap1(int a,int b)
{
    int temp;
    temp=a;
    a=b;
    b=temp;
}
有啥区别?其实没区别
你在函数里面修改的值,作用域仅在函数范围内,要跳出这个范围,你要么是全局变量,要么就是修改变量的地址
设想下,你现在传递一个一级指针作为参数,再函数里面进行操作,那么你要改变这个指针,是不是得修改指针的地址,那是啥,那就是二级指针
因此
按照你这个思路,
你要写成这样子才行

void swap(int **p1, int **p2)
{
        int *p; p = *p1; *p1 = *p2; *p2 = p;
}

void test5(){

                int *p1, *p2, a, b;
                a = 4; b = 5;
                p1 = &a;
                p2 = &b;
                if (a < b)
                {
                        swap(&p1, &p2);
                }
                printf("a=%d,b=%d\n", a, b);
                printf("max = %d,min = %d", *p1, *p2);

}

int main(void)
{
        test5();
        getchar();
        return 0;
}


冷回清风暖 发表于 2020-9-7 09:59:30

#include <stdio.h>

int main()
{
    void swap(int* p1, int* p2);
    int* p1, * p2, a, b;
    a = 4; b = 5;
    p1 = &a;
    p2 = &b;
    if (a < b)
    {
      swap(&p1, &p2);
    }
    printf("a=%d,b=%d\n", a, b);
    printf("max = %d,min = %d", *p1, *p2);
    return 0;
}

void swap(int** p1, int** p2)
{
    int* p; p = *p1; *p1 = *p2; *p2 = p;
}

建议从函数调用栈的角度解释
程序运行时,假定产生一个函数调用栈。
在主函数中执行另一函数时,会想堆栈中压入一个数据备份。
当这个备份执行完毕后,备份出栈,返回主函数。

你的主函数里面传入的参数是 :int *p1, * p2
到了堆栈里面函数得到的参数是:int *m=&a, int *n = &b,它们也指向对应数据;
此时函数内所有的操作只针对指针m,n进行,不会修改主函数传入的参数,这一部分也可以解释作用域的问题。

如果传入的是二级指针,堆栈得到的参数是:int** m = &p1,** n = &p2;
通过对二级指针解引用:*m = p1 = &a,*n= p2 = &b 获得主函数中指针p1,p2所指向的地址,进而利用临时一级指针变量修改主函数中一级指针指向的地址。

风过无痕1989 发表于 2020-9-8 01:11:58

兄弟,你只要记住,“变量有全局变量和局部变量之分,局部变量出了作用域就消毁了,不存在了” 就行了,其他的暂时弄不懂的暂时放过,留出时间来多做做练习,多看看其他的例题,慢慢地就会理解了,也就会懂了。我当时对这个问题就是通过比较弄懂的,下图就是我自己做的比较,希望对你的理解有所帮助:

悠幽我心 发表于 2020-9-9 11:01:09

风过无痕1989 发表于 2020-9-8 01:11
兄弟,你只要记住,“变量有全局变量和局部变量之分,局部变量出了作用域就消毁了,不存在了” 就行了,其 ...

好的,谢谢您,懂了懂了

悠幽我心 发表于 2020-9-9 11:01:40

冷回清风暖 发表于 2020-9-7 09:59
建议从函数调用栈的角度解释
程序运行时,假定产生一个函数调用栈。
在主函数中执行另一函数时,会想 ...

谢谢您,懂了懂了
页: [1]
查看完整版本: C语言址传递