簡體   English   中英

C-修改傳遞給函數的指針的地址

[英]C - modify the address of a pointer passed to a function

我不明白為什么在function外不保留對作為parameter傳遞給functionpointer地址的修改(調用該函數后ptr的地址不變):

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

當我可以在同一函數內修改ptr指向的value*ptr = *ptr + 1

PS:我知道使用pointer to a pointer **ptr pointer to a pointer可以實現我想要的功能。

這是因為C語言中函數的參數始終按傳遞。 您通過值傳遞的是一個地址。 修改ptr您正在修改調用方值的副本

要修改呼叫者的值,您需要額外的間接級別:

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

因為C 不是按引用調用,所以即使引用/指針作為參數 ,它也始終是按值調用

它與其他語言不同,可以區分參數類型。

當您定義函數void advance(int * ptr)時,這意味着將在堆棧中創建一個指針,該指針指向與原始指針相同的地址。 要查看證明,請嘗試打印原始指針的地址(&orig)和參數指針的地址(&param),以及“指向”的地址(orig,param)。 指針地址將有所不同,但指向的地址將相同。

因此,我們有兩個指向同一區域的指針,如果您修改參數,它將指向新區域,但是orig值不會改變,它指向與以前相同的區域。

這就是為什么需要一個指向指針的原因。 如果使用指向指針的指針(int ** ppointer =&orig),則將有一個指針直接指向orig存儲“指向”地址的區域(orig當前指向的區域)。 通過更改* ppointer的值,您也將直接更改orig的值。

您實際上回答了自己的問題;)

作為參數傳遞給函數的指針地址的修改不會在該函數之外持久存在

在函數內部,您正在管理參數的副本。 您可以修改指向的值,因為您明確要求在特定地址進行更改。

void advance(int *ptr)

該函數調用將在稱為ptr的堆棧中創建一個新變量(在Advance函數的堆棧中),該變量是指向整數的指針,隨着該函數的增加,該函數僅在退出advace函數后才起作用高級功能,變量丟失。 高級功能的堆棧不再存在

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

在這里, i是指向具有值2的存儲位置20的指針,即當將20 + sizeof(int) - 1的二進制數據解釋為十進制數時。 現在,當您將i傳遞給advance ,它具有一個參數ptr ,真正發生的是

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

ptr = i; 也就是說, i的值設置為ptr的值,因為iptr是指針,所以這里實際上是地址。

當您增加ptr它只會使指針指向一個不同的地址,而不會對i任何更改,因為ptr是一個副本而不是i本身。 但是,如果使用運算符*更改ptr處的值,即*ptr = 10 那么上面的2將更改為10從而也更改了*i ,它也指向20。再次注意, i的地址或值未更改,只有它指向的位置發生了更改。 如果有10個指向地址20指針,即使沒有指針被更改,但所有指向的值也都被更改。

見功能:

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM