指针混淆:c中的swap方法

Pointer Confusion: swap method in c

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

    /*int *p=b;
    b=a;
    a=p;
    */
}

int main(){
    int a,b;
    scanf("%d %d",&a,&b);
    swap(&a,&b);
    printf("%d %d",a,b);
}

上面是代码。

如果我将 3 5 作为输入,那么它应该交换它的值,并且 5 3 应该作为输出出现。 我通过尝试 int p=*b thing

得到了答案

但是我也试过注释部分,但是没有用。

所以,我检查了他们在 swap 和 main 中的地址。

交换 int *a 和 int *b 它们的地址改变了

然而,当我回到main时,a和b的地址并没有改变...

所以一开始我想:是不是在main里面没有改,因为参数int *a,int *b是局部变量?

但我还了解到,当指针和参数用作参数时,它们的值可能会发生变化,这与其他变量不同...

我真的很奇怪为什么第二种方法(注释部分)没有交换值...

在第二种方法中,您使用的局部变量被限制在函数的范围内swap。因此,main 函数中的变量 abswap 函数中定义为参数的变量 ab 不同。

当你使用指针时,swap函数会改变指针指向的值(即函数改变a和[=12地址处的值=] 在 main 函数中声明)。

假设你的意思是

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

该代码只是交换 swap() 函数中 指针 的值。这不会在 main() 中交换地址,因为正如您所说,"parameter int *a,int *b is local variable".

当你像这样调用函数swap()

swap(&a,&b);

ab地址被传递,成为swap()函数中的局部变量。您无法更改 ab 的地址 - 它们在内存中有一个位置。

在有效的代码中

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

您不更改指针的值,而是更改指针指向的内存中的值,这就是它起作用的原因。

虽然 C 是按值传递的,但如果您将某物的地址作为值传递给函数 可以 修改其范围之外的东西,因为您告诉函数该变量在哪里是。

在 C 中,函数中声明的所有变量都是该特定函数的局部变量。 所以,你在函数 swap

中写了一些东西

int *p=b;

上面的代码要做的是,它将b的复制到p中。所以,当函数swapreturn时,它的局部变量p,b,a就会消失

如果您想在函数中更改原始对象,您必须通过引用将它们传递给函数。

在 C 中,通过引用传递对象意味着通过指向原始对象的指针间接传递对象。

否则,如果您将原始对象本身传递给函数,函数将处理对象的副本。很明显,改变副本不会影响原始对象。

这正是这个函数中发生的事情

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

该函数处理传递给该函数的指针的副本作为此调用中的参数

swap(&a,&b);

这就是函数确实交换了声明为其参数的两个指针的值。但它们不是传递给函数的原始指针。它们是指针的副本。所以原始指针的值没有改变

函数交换一般可以看下面的方式

void swap( T *a, T *b )
{
    T tmp = *a;
    *a = *b;
    *b = tmp;
}  

其中 T 是相同的类型说明符。

所以如果你想交换 int 类型的对象,那么在上面的函数中 T 将是 int 并且函数看起来像

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

如果你想交换 int * 类型的指针的值,那么 T 将是 int * 并且函数看起来像

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

这是一个演示程序。

#include <stdio.h>

void swap1( int *pa, int *pb )
{
    int tmp = *pa;
    *pa = *pb;
    *pb = tmp;
}

void swap2( int **ppa, int **ppb )
{
    int *tmp = *ppa;
    *ppa = *ppb;
    *ppb = tmp;
}

int main(void) 
{
    int a = 3, b = 5;

    swap1( &a, &b );

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

    //  reset again the values of the variables
    a = 3; b = 5;

    int *pa = &a, *pb = &b;

    swap2( &pa, &pb );

    printf( "*pa = %d *pb = %d\n", *pa, *pb );

    return 0;
}

它的输出是

a = 5 b = 3
*pa = 5 *pb = 3

也就是一开始在程序中交换了两个int类型的对象,所以想象中的类型说明符T就是int.

然后交换指向对象 ab 的两个指针。所以想象中的类型说明符 T int *.

交换指针后,指针 pa 现在指向对象 b,指针 pb 现在指向对象 a