C - 修改传递给函数的指针的地址

时间:2014-02-03 10:21:49

标签: c pointers

我不明白为什么将pointer地址作为parameter传递给function的修改不会在此函数之外保留(ptr的地址不存在调用此函数后不要更改:

void advance(int *ptr) {
    ptr = ptr + 1
}  

当我可以在同一个函数中修改valueptr指向的*ptr = *ptr + 1时。

PS:我知道我可以使用pointer to a pointer**ptr实现我的目标。

7 个答案:

答案 0 :(得分:2)

这种行为是因为C中函数的参数总是通过传递。你在这里传递的价值是一个地址。当您修改ptr时,您正在修改来电者值的副本

要修改调用者的值,您需要额外的间接级别:

void advance(int **ptr) {
    *ptr = *ptr + 1;
} 

答案 1 :(得分:1)

因为C 通过引用调用,所以它总是按值调用,即使引用/指针作为参数

它与其他语言不同,它可以区分参数类型。

答案 2 :(得分:1)

当你定义函数void advance(int * ptr)时,它意味着将创建堆栈中的指针,该指针指向与原始指针相同的地址。要查看证明,请尝试打印orig指针(& orig)的地址和参数指针(& param)的地址,以及“指向”地址(orig,param)。指针地址会有所不同,但指向的地址将是相同的。

所以我们有两个指向同一区域的指针,如果修改参数,它将指向新区域,但是orig值不会改变,它指向与之前相同的区域。

这就是你需要一个指向指针的原因。如果你使用指向指针的指针(int ** ppointer =& orig),你将有一个指针直接指向orig存储“指向”地址的区域(当前的orig点)。通过更改* ppointer的值,您也可以直接更改orig的值。

答案 3 :(得分:0)

你实际上回答了你自己的问题;)

  

作为参数传递给函数的指针地址的修改不会在此函数之外持久存在

在功能内部,您正在管理参数的副本。 您可以修改指向的值,因为您明确要求在特定地址进行更改。

答案 4 :(得分:0)

void advance(int *ptr)

函数调用将在堆栈中创建一个名为ptr的新变量(在高级函数的堆栈中),这是一个指向整数的指针,递增它,只有当你进入advace函数时该函数才有效,退出高级功能后,变量将丢失。高级功能的堆栈不再存在

答案 5 :(得分:0)

******            /---\
* 20 * ---->      | 2 |
******            \---/
  i               20-24

此处i是指向存储位置20的指针,其具有值2,即当20 + sizeof(int) - 1中的二进制数据被解释为十进制数时。现在,当您将i传递给具有参数advance的{​​{1}}时,实际发生的是

******            /---\            ******
* 20 * ---->      | 2 |      <---- * 20 *
******            \---/            ******
  i               20-24             ptr

ptrptr = i;的值设置为i的值,这里的确是地址,因为ptri是指针。

当您递增ptr时,它只会使指针指向不同的地址而不会更改ptr的任何内容,因为i是副本,而不是ptr本身。但是,如果您使用运算符i更改ptr处的值,即*;然后上面的*ptr = 10会更改为2,从而也会更改10,这也会指向20.再次注意*i的地址或值未受影响,仅它所指向的位置经历了变化。如果有10个指针指向地址i,即使这样,它们也都没有被改变,但它们的所有指向值都会改变。

答案 6 :(得分:0)

见功能:

void demonstrate(int num) {
    num = num + 1;  // type of num is int
}   // destroys "num", because num's scope is only "demonstrate" function

在你的功能中:

void advance(int *ptr) {
    ptr = ptr + 1;  // type of ptr is int* and ptr is incremented
}   // destroys "ptr" for the similar reason

但是你想要一个修改地址的功能( IN 指针)。所以完整的解决方案应该是:

#include <stdio.h>

void advance(int **ptr) {   //ptr is a pointer to a pointer
    // so *ptr is the pointer that is pointed by ptr
    *ptr = *ptr + 1;    // incrementing the address IN the pointer pointed by ptr
}   // destroys "ptr" for the reason above

int main() {
    int x = 5;

    // initially assign "ptrToChange"
    int *ptrToChange = &x;
    // "ptrToChange" now points to x

    // passing address OF "ptrToChange" to "advance" function
    advance(&ptrToChange);
    // now "ptrToChange" does NOT point to x

    return 0;
}