为什么我不能使用函数交换两个变量的内存地址? C

时间:2015-10-22 14:03:48

标签: c pointers

static void swapAddr(int *numOne, int *numTwo)
{
    int *tmp;

    tmp = numOne;
    numOne = numTwo;
    numTwo = tmp;
}

int main(void)
{
    int a = 15;
    int b = 10;

    printf("a is: %d\n", a);
    printf("Address of a: %p\n", &a);
    printf("b is: %d\n", b);
    printf("Address of b: %p\n", &b);

    swapAddr(&a, &b);
    printf("\n");

    printf("a is: %d\n", a);
    printf("Address of a: %p\n", &a);
    printf("b is: %d\n", b);
    printf("Address of b: %p\n", &b);

    return 0;
}

当我编译并运行这段代码时,输​​出是

a is: 15
Address of a: 0x7fff57f39b98
b is: 10
Address of b: 0x7fff57f39b94

a is: 15
Address of a: 0x7fff57f39b98
b is: 10
Address of b: 0x7fff57f39b94

显然结果不是我想要的,因为地址似乎根本没有交换过。

7 个答案:

答案 0 :(得分:5)

您通常无法更改变量的地址。

您的'swapAddr'函数更改其参数值,但这些是函数的本地值 - 您不会更改函数外的任何内容。理解它的最佳方法可能是函数参数始终接收传递给函数的值的副本。在这种情况下,您会获得a地址的副本和地址b副本。您可以并且确实更改包含这些副本的变量的值(numOnenumTwo),并且看到它们是指针,您可以(但不要)更改它们指向的值(变量ab) - 但您无法更改原始变量的地址。

要打破它:

static void swapAddr(int *numOne, int *numTwo)
{
    int *tmp;

    tmp = numOne;

此时,tmpnumOne都指向a变量的值......

    numOne = numTwo;

现在,numOne指向b变量的值......

    numTwo = tmp;
}

最后,numTwo现在指向a变量的值。在该点之后,函数返回并且numOnenumTwo不再存在。变量ab的地址在任何阶段都没有变化。

可以然后编写一个函数来交换两个指针变量中的地址:

static void swapAddr(int **ptrOne, int **ptrTwo)
{
    int *tmp;

    tmp = *ptrOne;
    *ptrOne = *ptrTwo;
    *ptrTwo = tmp;
}

这将允许您传递两个指针变量的地址,并在返回时指针将被交换 - 每个指针指向另一个先前的指针。但同样,这不会改变那些指针碰巧指向的任何变量的地址。

答案 1 :(得分:3)

指针按值传递给函数,因此更改它们指向的内容不会改变调用函数中传递的参数的值。

调用该函数时,会生成每个指针的副本并保存到堆栈中。然后该函数从堆栈中读取每个指针值并对其进行操作。它永远不会更改复制到堆栈的原始指针的值。

答案 2 :(得分:2)

static void swapAddr(int *numOne, int *numTwo)

在此功能中,您按值传递2个指针。这允许您修改指针所指向的int,而不是指针本身。

使用此函数定义代替指针传递指针并允许自己修改指针

static void swapAddr(int **numOne, int **numTwo) {
    int *tmp = *numOne;
    numOne = *numTwo;
    numTwo = tmp;
}

你可以这样使用它,例如:

int *a = malloc(sizeof(int));
int *b = malloc(sizeof(int));
*a = 15;
*b = 10;
swapAddr(&a, &b);

答案 3 :(得分:2)

请记住,在C值中,按值传递给函数,这意味着要复制值。修改函数中的参数时,只修改函数内的本地副本,而不是传递给函数的原始值。这也适用于指针。

要解决您的问题,您必须通过引用传递参数,但不幸的是C没有,它只传递值。但是,通过将指针传递给数据,可以通过引用传递模拟,就像在函数中一样。但是,您必须取消引用指针以获取指针所指向的值,并使用这些值进行实际交换:

int temp = *numOne;  // Note: temp is a value not a pointer
*numOne = *numTwo;
*numTwo = temp;

答案 4 :(得分:1)

您无法更改地址。 a的加法器是a的地址,并且在日期结束前保持不变。

你可以这样做:

static void swapAddr(int **numOne, int **numTwo)
{
    int *tmp;

    tmp = *numOne;
    *numOne = *numTwo;
    *numTwo = tmp;
}

int main(void)
{
    int a = 15;
    int b = 10;
    int *pa= &a;
    int *pb= &b;
    swapAddr(&pa, &pb);
}

答案 5 :(得分:1)

您希望实现的目标是

int *c = &a;
&a = &b;
&b = &a;

这是不可能的(你可以检查:它不会编译)。创建的变量放在内存中的一个位置并保留在那里。因此,当您创建变量a时,它将保持变量a,并且无法将其身份更改为另一个变量b的身份。

你可以做的是使用两个指针int *p1, *p2来int。这些指针可以在生命周期内更改其值并指向其他对象:

p1 = a;
p2 = b;
p1 = b;
p2 = a;

ab将保持不变,但p1p2可以指向不同的对象。

这是可能的事情:

static void swapaddr(int **pp1, int **pp2)
{
    int *pp;
    pp = *pp1;
    *pp1 = *pp2;
    *pp2 = pp;
}

int main(void)
{
    int a = 15, b = 10;
    int *pA = &a, *pB = &b;
    swapAddr(&pA, &pB);
}

在此示例中,ab会保留其身份和地址,但pApB会更改其值,pA会指向{ {1}}和b会指向pB

答案 6 :(得分:0)

你不能改变变量的地址。但是你可以改变指针的值,它们将地址存储为它们的值,这是一个例子:

#include <stdio.h>

void swapAddr(int **numOne, int **numTwo)
{
    int *tmp;
    tmp = *numOne;
    *numOne = *numTwo;
    *numTwo = tmp;
}

int main(void)
{
    int a = 15;
    int b = 10;

    int *p_a = &a;
    int *p_b = &b;

    printf("Address of a: %p\n", p_a);
    printf("Address of b: %p\n", p_b);

    swapAddr(&p_a,&p_b);
    printf("\n");

    printf("p_a : %p\n",p_a);
    printf("p_b : %p\n",p_b);

    return 0;
}