我想将一个“多态”指针数组传递给一个函数。
我可以执行以下操作而不会发出警告:
foo (void* ptr);
bar()
{
int* x;
...
foo(x);
}
gcc显然会自动将
x
转换为dant的(void*)
。但是,当我执行以下操作时,我会收到警告:
foo (void** ptr);
bar()
{
int** x; // an array of pointers to int arrays
...
foo(x);
}
note: expected ‘void **’ but argument is of type ‘int **’
warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
我的问题是:为什么不将
(int*)
作为(void*)
参数传递,而将(int**)
作为(void**)
参数传递?由于所有指针类型的大小都相同(是吗?自从我使用C以来已经有一段时间了),
我仍然可以做类似的事情:
void mainFunc1(int** arr, int len)
{
//goal is to apply baz to every int array
foo(baz, arr, len);
}
void mainFunc2(double** arr, int len)
{
//goal is to apply baz to every int array
foo(qux, arr, len);
}
// I PROMISE that if I pass in a (int**) as ptr, then funcPtr will interpret its (void*) argument as an (int*)
void foo(funcPtr f, void** ptr, int len)
{
for(int i = 0; i < len; i++)
{
f(ptr[i]);
}
}
void baz(void* x)
{
int* y = (int*)x;
...
}
void qux(void* x)
{
double* y = (double*)x;
...
}
所有void指针的目的是使我可以将函数指针应用于应用于(在堆栈中)具有不同类型的ptr参数的函数:有些采用
int
数组,有些采用double
数组,依此类推。 最佳答案
注意:void*
是通用的。但是void**
不是。您可以将任何类型的地址分配给void*
变量,但是void**
只能分配给void*
变量的地址。
void* generic;
int i;
int *ptri = &i;
generic = ptri;
或者
char c;
int *ptrc = &c;
generic = ptrc;
有效,但以下是错误:
void** not_generic;
int i;
int *ptri = &i;
int **ptr_to_ptr1 = &ptri;
void** not_generic = ptr_to_ptr1;
错误:将
int**
分配给void**
。是的,您可以这样做:
void** not_generic;
not_generic = &generic;
对于通用数组函数,只需使用
void* a
,如下所示:enum {INT, CHAR, FLOAT};
void print_array(void* a, int length, int type){
int i = 0;
for(i = 0; i < length; i++){
switch(type){
case INT:
printf("%d", *((int*)a + i));
break;
case CHAR:
printf("%c", *((char*)a + i));
break;
case FLOAT:
printf("%f", *((float*)a + i));
break;
}
}
}
您最好使用宏编写此函数。
将该函数称为:
假设
int
: int a[] = {1, 2, 3, 4};
print_array(a, sizeof(a)/sizeof(a[0]), INT);
假设
char
: char a[] = {'1', '2', '3', '4'};
print_array(a, sizeof(a)/sizeof(a[0]), CHAR);
关于c - 使用和取消引用(无效**),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18951824/