2010-09-01 45 views
1

我有一个函数可以创建一个指针数组。分配内存的函数通过传递给函数的参数返回新的内存指针。它可以重现该问题的最简单的代码如下:实际参数指针不匹配?

void foo (void** new_mem, size_t bytes) 
{ 
    *new_mem = malloc(bytes); 
} 

int main (void) 
{ 
    int** ptr_arr; // Want to create an array of pointers 

    foo(&ptr_arr, sizeof(int*)*100); // Create an array size of 100 
            // compiler emits warning: 
            // 'void **' differs in levels of indirection from 'int ***' 

    return 0; 
} 

我能投传给foo的像这样的第一个参数:但是“(无效**)& ptr_arr”摆脱的警告,我想知道:是否有更合适的解决方案?

回答

0

尽管从int *void *有保证的转换,但从int **转换为void **并没有这样的保证。考虑这可能是为什么,请考虑int *实际上可能比void *小。因此,使用void **指针遍历int *的数组会走错误的步幅并获取错误的数据。此外,不能保证int *将使用与void *相同的表示形式,只是有一种方法可以在它们之间进行转换。

在实践中,我不知道任何机器哪里会失败。但这不是标准保证的。

编辑:eek,以及每个人都说通过int ***。但即使您通过int **,以上仍然适用。

编辑2:comp.lang.c常见问题有关于此的excellent discussion

+0

所以这听起来像解决方案是使用一个中间的'void *',它将包含新的内存地址,然后设置int **到中间void *。 – Andrew 2010-09-01 16:00:43

+0

@Andrew:不,使用中间的'void *'不会奇迹般地使转换有效。如果在'T *'和'U *'之间转换无效,那么'T *'将'void *'转换为'U *'也是无效的;但C不会提醒你。 – 2010-09-02 08:56:39

0

问题是你正在取得一个双指针的地址并将它传递给一个双指针参数。取一个值的地址创建一个指针,所以你最终得到一个三重指针int***,这就是为什么你会得到错误。

将结果投射到void**在技术上会在这里工作,尽管它与类型系统上的滥用有关。

+0

将一个'int ***'投射到'void **'是在寻找麻烦。如果你对编译器说谎,它会得到它的报复。 – 2010-09-01 15:43:45

+1

@Philip,它是C.即使你给它糖果,编译器也会制定它的报复。 – JaredPar 2010-09-01 15:52:27

0

麻烦的是ptr_arr已经是一个int **, 当你做一个&ptr_arr,它会显示为int ***,你在做什么这样是不正确。

所以,你可以通过ptr_arr如果你的目的是要传递一个int **

另外,我觉得你的代码可以与清理做得很好。你的方法似乎是错误的。

+0

除了'ptr_arr'不指向任何东西,'foo'指定给'* new_mem' – 2010-09-01 15:47:01

相关问题