在C函数中通过值传递指向指针的指针

3

fid_table是指向fid_list指针数组的指针。

我正在尝试在一个单独的函数中将fid_table初始化为NULL。我的理解是fid_table被按值复制,但它是一个指针,所以这不应该是问题。

fid_list **fid_table;
fid_table_init(fid_table);
assert(fid_table[0] == NULL);

函数fid_table_init的定义如下:

void fid_table_init(fid_list **fid_table){
    fid_table = (fid_list **) malloc(HTABLE_SIZE * sizeof(fid_list *));
    for(int i = 0; i < HTABLE_SIZE; i++){
        fid_table[i] = NULL;
    }
}

有人能解释一下为什么这个断言失败吗?

这是C还是C++?在C中,您不应该转换void *,而在C++中,您必须这样做。请选择一种语言。 - too honest for this site
好的,我不会问你为什么添加了C++标签。所以:标准警告:不要强制转换void * - too honest for this site
1
我的理解是fid_table是按值复制的,但它是一个指针,所以这不应该是问题所在。不是的。你可能将指针与数组混淆了。在调用fid_table_init时,您将需要取一个指向fid_table的指针。 - user707650
2个回答

5
用以下方式定义函数:
void fid_table_init(fid_list ***fid_table){
    *fid_table = (fid_list **) malloc(HTABLE_SIZE * sizeof(fid_list *));
    for(int i = 0; i < HTABLE_SIZE; i++){
        ( *fid_table )[i] = NULL;
    }
}

并且像这样调用它

fid_table_init( &fid_table );

在原函数中,指针是按值传递的,这意味着该函数处理指针的副本。因此,对副本进行的任何更改都不会影响原始指针。
请注意,函数的参数是其局部变量。因此,在函数内部分配了一个内存并将其地址分配给函数的局部变量。被分配的是局部变量,而不是原始指针。在退出函数后,它的局部变量将被销毁。原始指针不知道其副本被执行了什么操作。

那看起来有点糟糕(并不意味着它是错误的!)。三星函数。 - too honest for this site
@Olaf 想象一下,就像一杯三星级的干邑酒一样。 :) - Vlad from Moscow
1
恭喜你:你已经解锁了三星程序员徽章! - bolov
3
函数的参数是其局部变量。因此,在函数内部,您分配了一个内存,并将其地址赋给了函数的局部变量。被赋值的是局部变量而不是原始指针。在退出函数后,它的局部变量将被销毁。原始指针不知道其副本所做的任何事情。 :) - Vlad from Moscow
1
...然后引用基本上就是指针加上自动解引用,减去了可以为空或重新分配的能力;-) 即使在C++中,在许多情况下选择它们之间也可能很困难。 - underscore_d
显示剩余4条评论

5
fid_table_init函数中,fid_table是一个本地变量,它被初始化为从调用者传递的值。 malloc行更改了局部变量的值,而没有更改调用者中的fid_table的值,因此调用代码从未看到malloc返回的指针。
修复代码最简单的方法是从fid_table_init函数返回指针的新值,并将其分配给调用者中的fid_table
fid_list **fid_table = fid_table_init();
assert(fid_table[0] == NULL);

fid_list **fid_table_init( void )
{
    fid_list **temp = malloc(HTABLE_SIZE * sizeof(fid_list *));
    for(int i = 0; i < HTABLE_SIZE; i++){
        temp[i] = NULL;
    }
    return temp;
}

感谢您的解释! - Keeto
很高兴能帮助,愉快编码! - user3386109

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接