我在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);
}
答案 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并再次返回;结果应该等于 原始指针。