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

void** pointer and void*[] as function parameters

我收到以下警告: 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**) 投射 arr 时它起作用了,我找不到这样做的原因。此外,我发现我还需要输入以下代码:

#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 的指针,我们可以传递给它任何我们想要的指针而无需强制转换,因为所有指针的大小都相同那么为什么我不能传递一个指向指针也一样吗?

所有对象指针类型,包括 int *,都保证 可以与 void * 互换,但它们不能 互换。类型 int * 的表示不必与类型 void * 的表示相同(尽管在实践中几乎总是如此),因此没有从指针到 [=10 的自动转换=](即int **)指向指向void *(即void **)的指针。假设一种 pointed-to 类型的事物可以正确地 re-interpreted 作为另一种 pointed-to 类型的事物是不安全的。

请注意,顺便说一句:

if a function's parameter is a pointer to void we can pass to it whatever pointer we want without casting because all pointers are of the same size

是一个不正确的表征。指针 不需要 都具有相同的大小。只需要每个对象指针都可以 转换 类型 void * 并返回,并且这种 round-trip 转换的结果等于原始指针.

请牢记@Lundin 的评论:数组不是指针。尽管如此,在大多数情况下,数组类型的值 会衰减 到指针,包括当它们作为函数参数或作为赋值运算符的 right-hand 操作数出现时。

你的第二个代码片段有几个问题:

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 * 可能有不同的表示。将指向 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;
}