2010-11-11 77 views
1

我想了解如何通過C語言參考傳遞參數。 所以我寫這個代碼來測試參數傳遞的行爲:瞭解通過參考動態分配傳遞參數

#include <stdio.h> 
#include <stdlib.h> 

void alocar(int* n){ 
    n = (int*) malloc(sizeof(int)); 
    if(n == NULL) 
     exit(-1); 
    *n = 12; 
    printf("%d.\n", *n); 
} 
int main() 
{ 
    int* n; 
    alocar(n); 
    printf("%d.\n", *n); 
    return 0; 
} 

在這裏被印刷:

 
12. 
0. 

實施例2:

#include <stdio.h> 
#include <stdlib.h> 

void alocar(int* n){ 
    *n = 12; 
    printf("%d.\n", *n); 
} 

int main() 
{ 
    int* n; 
    n = (int*) malloc(sizeof(int)); 
    if(n == NULL) 
     exit(-1); 
    alocar(n); 
    printf("%d.\n", *n); 
    return 0; 
} 

它印刷:

 
12. 
12. 

Wha t是這兩個程序的區別?

+0

指針不是整數。你的格式說明符應該是'%p',而不是'%d'。在你的第一個例子中(現在你明白了爲什麼),'n'永遠不會被初始化,所以使用它會給你一個未定義的行爲。什麼事情都可能發生。 – GManNickG 2010-11-11 20:46:16

+0

正確的單位化指針,但格式說明符本身在這些示例中是正確的。 – Kos 2010-11-12 13:37:00

回答

6

C是通過值,它不提供通過引用。 在你的情況下,指針(不是它指向)複製到功能paramer(指針是按值傳遞 - 指針的值是一個地址)

void alocar(int* n){ 
    //n is just a local variable here. 
    n = (int*) malloc(sizeof(int)); 
    //assigning to n just assigns to the local 
    //n variable, the caller is not affected. 

你想要的東西一樣:

int *alocar(void){ 
    int *n = malloc(sizeof(int)); 
    if(n == NULL) 
     exit(-1); 
    *n = 12; 
    printf("%d.\n", *n); 
    return n; 
} 
int main() 
{ 
    int* n; 
    n = alocar(); 
    printf("%d.\n", *n); 
    return 0; 
} 

或者:

void alocar(int** n){ 
    *n = malloc(sizeof(int)); 
    if(*n == NULL) 
     exit(-1); 
    **n = 12; 
    printf("%d.\n", **n); 
} 
int main() 
{ 
    int* n; 
    alocar(&n); 
    printf("%d.\n", *n); 
    return 0; 
} 
+0

我想這是一個問題,但我會說地址運算符可以通過引用傳遞值。 – Christoffer 2010-11-11 20:58:29

+0

@Christoffer:這將是一個事實上的術語,但它仍然是一個價值。 – GManNickG 2010-11-11 21:03:34

+0

這是真的。 C不支持通過引用。所以實際上我不會把地址傳給'aloca',因爲n沒有存儲地址。 – adriano 2010-11-11 21:29:48

3

其實算不上多大的差別,除了第一個被打破了。 :)(好吧,都是,但第一個是更多)。

讓我解釋一下在第二種情況下會發生什麼:

  • 變量pointer-to-intn
  • int類型的新變量被分配到堆棧中的棧上分配,它的地址存儲在變量n
  • 功能alocar被調用,通過變量n的副本,這是我們的變量的地址的副本int
  • 函數設置int變量被指向通過n至12
  • 功能打印的變量由n(12)指出的值
  • 該函數返回

第一種情況:

  • 可變pointer-to-int類型的n被分配在堆棧上
  • 功能alocar被稱爲與可變n的副本(這仍然是未初始化 - 包含未知的值)
  • int類型的新變量在內存中創建和可變n的在功能alocar本地副本被設置
  • 由於原n變量:以指向新的變量
  • 變量(由函數的本地的n拷貝指出)在main()函數設置爲12和印刷
  • 函數返回時,再次在主要仍然是itialized,它指向一個隨機的地方在記憶中。所以打印內存隨機位置的值(這可能會導致程序崩潰)。

此外,兩個程序都被破壞,因爲它們沒有釋放由malloc()分配的內存。

+0

我知道這是需要釋放分配的內存。我通常免費它。我理解你的解釋。你是對的。非常感謝!!! – adriano 2010-11-11 21:20:05

+0

很高興我幫助了:),請記住,在SE上,每次有問題回答時,請在您最喜歡的答案旁邊打勾綠色標記,以表明問題已解決(並分數點美味點, !:))。 – Kos 2010-11-12 13:35:53

0

nos發佈的答案是正確的。

還要注意,第一二公佈的方案實際上會崩潰,在許多系統中,當在main()中的printf行試圖取消引用主要的指針n,這是從來沒有設置:

printf("%d.\n", *n); 
1

你想修改n的值main,而不是n指向,所以你需要傳遞一個指針給它。由於nmain類型是int *,該參數alocar需求是int **類型:

void alocar(int **n) 
{ 
    *n = malloc(sizeof **n); // note no cast, operand of sizeof 
    if (!*n) 
    exit(-1); 

    **n = 12; 
    printf("%d\n", **n); 
} 

int main(void) 
{ 
    int *n; 
    alocar(&n); 
    printf("%d\n", *n); // we've already tested against n being NULL in alocar 
    free(n);    // always clean up after yourself 
    return 0; 
} 
0

見,發生了什麼事的第一個程序。

調用之前alocar我們剛纔變量n主,指着一些不確定的地方:

main()::n [ X--]--->(?) 

(有一個在方括號內的值,這是不確定的,記爲X)。然後我們稱之爲alocar,在alocar的範圍內有另一個變量,它們有origianl var的副本。

main()::n [ X--]--->(?) 
alocar()::n [ X--]-----^ 

現在,分配一些內存:

main()::n [ X--]--->(?) 
alocar()::n [ *--]--->[ Y ] 

值分配給分配VAR:

main()::n [ X--]--->(?) 
alocar()::n [ *--]--->[ 12 ] 

返回。 alocar():: n被移除,因爲它只在alocar()被執行時才活着。

main()::n [ X--]--->(?) 
         [ 12 ] 

main():: n仍然指向一些未定義的地方...(可能存儲值爲0)並且沒有人指向分配的地方。