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.
A void pointer cannot be dereferenced. We get a compilation error if we try to dereference a void pointer. This is because a void pointer has no data type associated with it. There is no way the compiler can know what type of data is pointed to by the void pointer.
You cannot. Dereferencing a void pointer requires an explicit cast beforehand. You can ofcourse cast it to any particular type and then dereference it without knowing its original type, but why you would want to do that is beyond me.
Since void is an incomplete type, it is not an object type. Therefore it is not a valid operand to an addition operation. Therefore you cannot perform pointer arithmetic on a void pointer.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With