I would like to pass a "polymorphic" array of pointers to a function.
I can do the following without warnings:
foo (void* ptr);
bar()
{
int* x;
...
foo(x);
}
gcc apparently automatically casts x
to a (void*)
, which is just dandy.
However, I get a warning when I do the following:
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]
My question is: why is passing an (int*)
as a (void*)
argument not 'incompatible', but (int**)
as a (void**)
argument is?
Since all pointer types are the same size (right? it's been a while since I've used C), I can still do something like:
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;
...
}
The purpose for all the void pointers is so that I can use a function pointer applied to functions that will (down the stack) have different types of ptr arguments: some will take int
arrays, some will take double
arrays, etc.
Note: void*
is generic. but void**
is not. You can assign address of any type to void*
variable but void**
can be assigned address of void*
variable only.
void* generic;
int i;
int *ptri = &i;
generic = ptri;
or
char c;
int *ptrc = &c;
generic = ptrc;
valid but following is an error:
void** not_generic;
int i;
int *ptri = &i;
int **ptr_to_ptr1 = &ptri;
void** not_generic = ptr_to_ptr1;
Error: assigning int**
to void**
.
Yes you can do like:
void** not_generic;
not_generic = &generic;
For generic array function simply use void* a
as follows:
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;
}
}
}
You better write this function using macros.
Call this function as:
Suppose int
:
int a[] = {1, 2, 3, 4};
print_array(a, sizeof(a)/sizeof(a[0]), INT);
Suppose char
:
char a[] = {'1', '2', '3', '4'};
print_array(a, sizeof(a)/sizeof(a[0]), CHAR);
Because there is no generic pointer-to-pointer type in C.
Reference: C FAQ Question 4.9
The short answer is: anything that resembles
<datatype>* <variable_name>
can be passed in where the parameter declaration is of type void* because void* is generic. However, void** is not. So automatic casting fails.
来源:https://stackoverflow.com/questions/18951824/using-and-dereferencing-void