2015-07-21 62 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