2015-12-21 59 views
0

我不明白爲什麼ARR沒有指向我已在功能測試中取得的數組:定義函數內數組指針

void test(int *arr) 
{ 
    int tmp[] = {2,4}; 
    arr = tmp; 
    printf("%d %d\n",arr[0],arr[1]); 
} 

int main() 
{ 
    int *arr; 
    test(arr); 
    printf("%d %d\n",arr[0],arr[1]); 
    return 0; 
} 

當我運行這個程序我:

2 4 
17744 786764 

arr是指針,爲什麼不更新值?

更新: 我現在看到我誤解了很多關於指針和函數本地變量的問題。已經更新我的小笨笨的腳本,以適用的東西:

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

void test(int *arr){ 
    arr[0] = 123; 
    arr[1] = 321; 

    printf("%d %d\n",arr[0],arr[1]); 
} 

int main() 
{ 
    int arr[2]; 
    test(arr); 
    printf("%d %d\n",arr[0],arr[1]); 
    return 0; 
} 
+0

因爲你是按值傳遞指針 - 所以你只能改變它在你的'test'功能的本地副本... – dragosht

+0

以及如何將arr'的''在副本main'得到更新? –

回答

2

它因爲在C中的參數通過值傳遞。 arr您正在通過main只是複製到功能參數arr
作業arr = tmp;使arr指向新位置。 現在arr指向一個自動局部變量,並且一旦函數達到其結尾就不會存在。
因此,在main

printf("%d %d\n",arr[0],arr[1]); 

的語句調用未定義的行爲。

你的函數改爲

void test(int **arr) // Change parameter to pointer to pointer to int 
{ 
    int *tmp = malloc(2*sizeof(int)); // Allocate memory dynamically 
    tmp[0] = 2; 
    tmp[1] = 4; 
    *arr = tmp; 
    printf("%d %d\n", (*arr)[0], (*arr)[1]); 
}  

main稱呼其爲

test(&arr); 
1

這是因爲在C參數通過值通過,這意味着它們的值複製和功能只有副本。修改副本當然不會修改原始內容。在main函數中,當test返回時變量仍將未初始化,導致未定義行爲當您試圖對其進行解引用時。

C沒有通過引用,但它可以使用指針進行仿真。在你的情況下,你必須傳遞一個指針指向指針。

但是,這並不是全部,你嘗試設置指向一個局部變量的指針,局部變量,以及本地。它們的生命週期在函數返回時結束,並且一旦函數返回,指向它們的指針就不會有效。

有兩種方法可以解決這兩個問題。第一個問題是通過使用地址的操作者將指針傳遞到指針解決,即

test(&arr); 

test功能必須相應地修改以處理指針指向int

第二個問題可以通過幾種方法解決。最簡單的方法是延長變量的生命週期,以便即使在函數返回後,它也會繼續生存。基本上只有兩種方法:將變量設置爲全局變量,或將其設置爲局部變量static。解決第二個問題的另一種方法是使用malloc動態分配數組,但是一旦完成了該操作,您就必須記住free以避免內存泄漏。

1

您通過值傳遞指針(C已僅由值通過),即指針的副本被創建指向整數數組。因此,有在指針的初始值沒有變化在main

如果你願意,你需要傳遞指針的地址,但在這種情況下,也訪問它在main也會造成問題,因爲tmp是一個局部變量,其範圍將只保持有限的功能test

所以在main當您嘗試打印指針的內容(這是未初始化)將調用未定義行爲

1
  1. 參數按值傳遞。因此,您只修改副本,而不是實際參數。要真正修改main中的arg,請使用指向指針的指針。
    定義你的函數是這樣的:

    void test(int** arr) 
    

    ,並取消對它的引用的函數從main修改arr。此外,呼叫test這樣,而不是:

    test(&arr); 
    
  2. 自動變量超出範圍的功能已經恢復,並給他們的任何進一步的訪問是不確定的行爲。這意味着使用main中的數組也是未定義的。
    爲了防止這種情況,你可以使陣列static

    static int tmp[] = { 0, 2 }; 
    

    就這樣,tmp初始化只一次存在在整個運行,因此不未定義的行爲。