2015-07-21 43 views
0

我此刻再學習C和寫了一小段測試代碼,同時參照審查合格不工作:困惑,爲什麼經過字符**參照預期

#include <stdio.h> 
#include <string.h> 

void distort_flags_list(char*** flags); 

int NUM_FLAGS = 2; 

int main(int argc, char** argv) 
{ 
    distort_flags_list(&argv); 

    for (int flag_offset = 0; flag_offset < NUM_FLAGS; flag_offset++) { 
     printf("%s\n", *(argv + flag_offset)); 
    } 

    return 0; 
} 

void distort_flags_list(char*** flags) 
{ 
    char* tester[2] = {"first", "second"}; 
    *flags = tester; 
} 

我很好奇運行這個時候爲什麼,我得到下面的輸出:

first 
(null) 

,而不是將它打印「第一」,「第二」。據我的理解,當將指針傳遞到argvdistort_flags_list時,您正在改變指針指向該函數中定義的地址tester的地方。

爲什麼會發生這種情況的任何解釋?

+2

沒有通通過在C基準,只按值傳遞。 – ericbn

+1

您正在將函數內部的一個指針傳遞給本地變量('tester')給它的調用者。這是一面紅旗。你正確地使用了傳遞引用,但是你通過引用傳遞的值指向堆棧中的回收內存,所以指向''second''的指針的地址被'0'偷偷地覆蓋。 – mooiamaduck

+0

@Gopi Ref。 [Call By Value](https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value) – user2864740

回答

2

在功能distort_flags_list中,您將*flags的值設置爲一旦函數返回就無效的值。

撥打distort_flags_list後,訪問argv的任何內容都是未定義的行爲。

爲確保在函數返回後值*flags繼續有效,您需要使用動態內存分配。

void distort_flags_list(char*** flags) 
{ 
    *flags = malloc(2*sizeof(**flags)); 
    (*flags)[0] = malloc(20); // Make is large enough 
    (*flags)[1] = malloc(20); // ditto 
    strcpy((*flags)[0], "first"); 
    strcpy((*flags)[1], "second"); 
} 

然後,添加代碼以釋放main中的內存。

int main(int argc, char** argv) 
{ 
    distort_flags_list(&argv); 

    for (int flag_offset = 0; flag_offset < NUM_FLAGS; flag_offset++) { 
     printf("%s\n", *(argv + flag_offset)); 
    } 

    free(argv[1]); 
    free(argv[0]); 
    free(argv); 

    return 0; 
} 
+0

這很有道理。我應該在'distort_flags_list'內使用'malloc'來爲'tester'預留內存空間嗎? – Ryan

+1

@Ryan,如果你希望指針在函數返回後仍然有效,那麼答案是肯定的。你需要使用'malloc'來分配內存。當然,那麼你必須添加調用'free'來釋放內存。 –

2

局部變量不能使用的功能塊外。你可以使用上面的方法也可以使用關鍵字static的。

static char* tester[2] = {"first", "second"}; 

因此tester保持其值直到程序結束。

看到演示在這裏 - https://ideone.com/eLDn3m