5

有人可以向我解释/解释为什么下面代码片段中主函数中变量 i 的值不会通过函数 test1 更改而通过 test2 更改吗?我认为单个指针应该足以改变 i 的值。为什么我们应该使用双指针?

#include <stdio.h>

void test1(int* pp)
{
   int myVar = 9999;
   pp = &myVar;
}

void test2(int** pp)
{
   int myVar = 9999;
   *pp = &myVar;
}

int main()
{
   printf("Hej\n");
   int i=1234;
   int* p1;

   p1 = &i;

   test1(p1);
   printf("does not change..., p1=%d\n",*p1);

   test2(&p1);
   printf("changes..., p1=%d\n",*p1);
   return 0;
}
4

7 回答 7

6

在 C 中,参数是按值传递的。这意味着test1当您传递pp一个副本时,是由指针组成的,当您更改它时,更改是针对副本而不是指针本身。test2副本是双指针,但是当您取消引用并在此处分配时

*pp = &myVar;

您正在更改所指向的内容,而不是更改pp自身。请注意,此行为test2未定义,如此处的其他一些答案中所述

于 2012-12-04T12:36:47.780 回答
4

但是您并没有更改 的值,而是更改了指向i的地址pp,如果您只想更改 的值,i那么将测试更改为:

void test3(int* pp)
{
   int myVar = 9999;
   *pp = myVar;
}
于 2012-12-04T12:38:26.887 回答
3

如果要更改类型变量的值,T则必须使用该类型 ( T*) 上的指针。由于您要更改指针 ( T = int*),因此您必须提供指向指针 ( T* = int**) 的指针,否则您只会更改副本。

注意

int myVar = 9999;
*pp = &myVar;

将导致未定义的行为,因为pp现在将包含退出函数后无效的局部变量的地址。

于 2012-12-04T12:37:17.290 回答
2

因为f(x)不能改变 的值x,无论 x 是 int、float 还是指针。

于 2012-12-04T12:37:38.053 回答
2
void test1(int* pp)
{
   int myVar = 9999;
   pp = &myVar;
}

这个函数被传递了一个指针pp。该函数修改该指针。但是由于参数是按值传递的,调用者看不到该修改。

您需要编写如下函数:

void test1(int* pp)
{
   *pp = 9999;
}

这个函数的调用者应该传递一个int变量的地址。然后该函数将一个int值(在本例中为 9999)写入该地址。这是关键。你被传递了一个地址,然后你将一个值写入该地址。您损坏的版本只是修改了地址。你错过了间接性。

当函数返回时,调用者可以观察到int地址被传递给函数的变量的修改。调用代码可能如下所示:

int i = 0;
test1(&i); // pass address of int variable
printf("%d\n", i); // prints the new value, 9999

void test2(int** pp)
{
   int myVar = 9999;
   *pp = &myVar;
}

现在,这被严重破坏了。这个函数确实返回了一个指向调用者的指针。但是它会返回一个指向对象的指针,该对象在函数返回后立即超出范围。这就是所谓的未定义行为。不要这样做。永远不要从函数中传递一个指向该函数中定义的局部变量的指针。

于 2012-12-04T12:38:58.637 回答
1
int* p1;

   p1 = &i;

   test1(p1);  //1st

   test2(&p1);  //2nd

简单来说,第一个是pass by value,第二个是pass by address

描述 :

在第一种情况下,它传递的指针实际上是内部的副本,p因此test1内部pptest1 是该函数的本地,它是在test1. 您分配了地址,当它失去功能时,它被破坏了。

但在第二种情况下,您将指针的地址传递给test2函数。因此ppin 中的指针test2将指向 main 中的指针,因此为usingp分配一个新地址将自动设置 of 的值(因为您正在取消引用指针)。因此,当终止时仍将指向修改后的位置。pp*pp = &myVarptest2p

于 2012-12-04T12:37:43.330 回答
1

pp = &myVar;将 的地址分配给myVar指针pp。如果要更改pp指向的值,请使用

*pp = myVar;

反而。

在回答您的第二个问题时,当您想要更改指向的对象而不是更改现有对象的值时,请将指针传递给指针。

于 2012-12-04T12:38:16.143 回答