Void **作为参数需要强制转换

时间:2016-04-14 07:50:28

标签: c void-pointers

我在C中有一个函数需要接收一个指向数组的指针(具有未指定的类型)。

为此,我使用void **,因为我将使用void *来接收未指定元素的数组。

遗憾的是有一个问题:编译器发出警告(从不兼容的指针类型传递' f'的参数1)。如果我忽略警告,并尝试执行程序,一切都按预期工作。

摆脱警告的唯一方法是将我尝试传递给函数的任何内容转换为void **。

为什么C表现得那样?有没有更好的方法来解决警告?

PS:我需要使用GCC编译标志-std = gnu89 -pedantic -Wall

示例

int f(void** param){ return 1; }

int main(){
    int *arr = malloc(sizeof(int) * 20);
    int i;
    for(i=0; i < 20; i++) arr[i] = i;
    f(&arr);
}

3 个答案:

答案 0 :(得分:3)

指向任何类型的指针都是.success(data,status,headers,config),编译器不会抱怨转换为该类型。但void*不是指向任何东西的指针,它是指向任何东西的指针数组的指针,这与指向整数指针数组的指针完全不同,因此编译器抱怨。 所以,要解决警告,是的,你需要明确地进行投射。

答案 1 :(得分:2)

您似乎想要修改函数内部的数据地址(而不是值),不能直接使用void *来执行此操作,因为您无法使用算术{{1}但是你可以传递第一个元素和一大块字节(void *)的大小,假设你想要将char *的地址改为arr(第二个元素)数组内部的函数:

arr + 1

输出:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void f(void *ptr, size_t size)
{
    // char *p = *ptr;  Wrong, you can't dereference a void * without a cast
    char *p = *(char **)ptr; /* pointer to address of ptr */

    memmove(p, p + size, size); /* assign the address of ptr + 1 to ptr */
}

int main(void)
{
    int *arr = malloc(sizeof(int) * 20);
    int i;
    for (i = 0; i < 20; i++) arr[i] = i;
    f(&arr, sizeof arr[0]);
    printf("%d\n", arr[0]);
    return 0;
}

答案 2 :(得分:1)

虽然void *是C中的“通用指针”,但void **不是“指向指针的通用指针”。相反,它只不过是指向void *的“特定指针,通用指针”。

在您的情况下,int **会隐式转换为void **,这不是通用的。由于不能保证void **能够保存所有指针变量(因此与int **不兼容),编译器会发出警告。

以下是clang生成的警告:

main.c:7:7: warning: incompatible pointer types passing 'int **' to parameter of
      type 'void **' [-Wincompatible-pointer-types]
    f(&arr);
      ^~~~
main.c:1:14: note: passing argument to parameter 'param' here
int f(void** param){ return 1; }

要消除此警告,您可以int f(void* param);,并在功能内部param投射int **。没有警告,因为void *可用于存储任何指针(引自N1570):

  

6.3.2.3指针

     

1指向void的指针可以转换为指向any的指针   对象类型。指向任何对象类型的指针可以转换为   指向void并再次返回;结果应该等于   原始指针。