代码之家  ›  专栏  ›  技术社区  ›  Uri Greenberg

void**指针和void*[]作为函数参数[duplicate]

  •  5
  • Uri Greenberg  · 技术社区  · 9 年前

    我收到以下警告: incompatible pointer types 'void**' and 'int* [2]' .

    当我尝试编译以下代码时:

    #include <stdlib.h>
    
    void func1(void *arr[]) { }
    
    int main() {
        int *arr[2];
        for (int i = 0; i < 5; i++) {
            arr[i] = (int*)malloc(sizeof(int));
            *(arr[i]) = 5;
        }
        func1(arr);
    }
    

    现在,当我用 (void**) ,我找不到原因。此外,我发现我还需要转换以下代码:

    #include <stdlib.h>
    
    void func1(void **arr) { }
    
    int main() {
        int **arr;
        int i[] = { 1, 2 };
        int j[] = { 3, 4 };
        *arr = i;
        *(arr+1) = j;
        func1(arr); //Doesn't compile unless I use (void*) or (void**) casting
    }
    

    我知道如果函数的参数是指向 void 我们可以向它传递我们想要的任何指针,而不必强制转换,因为所有指针都是相同的大小,那么为什么我不能以相同的方式向指针传递指针呢?

    2 回复  |  直到 9 年前
        1
  •  4
  •   chqrlie    9 年前

    第二个代码段有几个问题:

    void func1(void** arr) { }
    int main() {
        int** arr;
        int i[] = {1,2};
        int j[] = {3,4};
        *arr = i;
        *(arr+1) = j;
        func1(arr); //Doesn't compile unless I use (void*) or (void**) casting
    }
    

    您从未初始化 arr 指向指向的指针或指针数组 int 。它未初始化,因此其值可以是任何值。当您设置 *arr i ,调用未定义的行为。

    此外 int ** void ** 不是可互操作的类型,不能隐式地将一个转换为另一个。其原理是,在一些罕见的系统上, int * void * 可以具有不同的表示。将指针投射到 整数* 作为指向 空隙,空隙* 将与向 float 作为指向 double 。在表示相同的系统上,您只需编写显式转换即可。

    以下是一个更正版本:

    #include <stdlib.h>
    
    void func1(void **arr) { }
    
    int main(void) {
        int *int_pointer_array[2];
        int **arr = &int_pointer_array;
        int i[] = { 1, 2 };
        int j[] = { 3, 4 };
        *arr = i;     /* this line modifies int_pointer_array[0] */
        *(arr+1) = j; /* this line modifies int_pointer_array[1] */
        func1((void **)arr);
        return 0;
    }
    
        2
  •  2
  •   John Bollinger    9 年前

    所有对象指针类型,包括 int * ,保证 可相互转换的 具有 void * ,但它们不是 可交换的 .类型的表示 整数* 不必与类型的表示形式相同 空隙,空隙* (尽管在实践中,几乎总是这样),因此没有从指针到 整数* (即。 int ** )指向的指针 空隙,空隙* (即。 void ** ). 假设一种类型的指向对象可以正确地重新解释为另一种指向类型的对象是不安全的。

    顺便说一下,请注意:

    如果一个函数的参数是指向void的指针,我们可以向它传递我们想要的任何指针,而不必强制转换,因为所有指针的大小都相同

    是不正确的特征。指针是 要求所有尺寸相同。只要求每个对象指针都可以 转换 要键入 空隙,空隙* 并且这种往返转换的结果等于原始指针。

    请记住@Lundin的评论:数组不是指针。然而,数组类型的值确实 衰退 在大多数情况下,包括当指针作为函数参数或赋值运算符的右操作数出现时,指针都可以指向指针。