I'm passing a pointer to my function, but the type of this pointer may change. I don't want to write several versions of this function such as func_float()
and func_int()
. So I'm passing a pointer of void*
to my function and then type casting to int*
or float*
which depends on an argument type
. Here's my code:
void func(void* pSrc, float* pDst, int len, int type)
{
if (type == 0)
float* pIn = (float*)pSrc;
else
int* pIn = (int*)pSrc;
float* pOut = pDst;
while (len--)
*pOut++ = (float)*pIn++ * 2.0; // cast to float and then do some math
}
int main()
{
int input[3] = { 1,2,3 };
float output[3] = { 0 };
func(input, output, 3, 1);
return 0;
}
But this seems not work. VS told me that a dependent statement may not be a declaration
. I tried to declare pIn
as void*
before if
, but I got another error expression must be a pointer to a complete object type
when I dereference the pointer pIn
.
Any help would be appreciated.
You are, in effect, trying to make the type of your pIn
variable differ, depending on the value of the passed-in type
flag. But there's no way to do that. Each variable must have exactly one type, known at compile time.
The closest you could achieve to what you're trying to do would probably be something like this:
void func(void *pSrc, float *pDst, int len, int type)
{
char *pIn = pSrc; /* char * so can do pointer arithmetic */
float *pOut = pDst;
while (len--) {
*pOut++ = (type == 0 ? *(float *)pIn : *(int *)pIn) * 2.0;
if (type == 0)
pIn += sizeof(float);
else pIn += sizeof(int);
}
}
This is kind of an ugly kludge, however. If your actual func
is more complicated, it might be worth it. But if all you're doing is multiplying by 2, it would probably cleaner to just bite the bullet and use two separate functions. (Sorry, I know you said that's not what you wanted to do.)
The subexpression (type == 0 ? *(float *)pIn : *(int *)pIn)
is somewhat of a jawbreaker as I've written for. (C is both celebrated, and notorious, for allowing this kind of pithiness.) You might prefer to write things out in a more "longhand" way:
void func(void *pSrc, float *pDst, int len, int type)
{
char *pIn = pSrc; /* char * so can do pointer arithmetic */
float *pOut = pDst;
while (len--) {
double inVal;
if (type == 0) {
inVal = *(float *)pIn;
pIn += sizeof(float);
} else {
inVal = *(int *)pIn;
pIn += sizeof(int);
}
*pOut++ = inVal * 2.0;
}
}
This second formulation would also make things easier and cleaner if you have more different values for type
, or if you're doing more involved things with inVal
.
Addendum: Here's a completely different approach. In your original problem statement, you had either an array of int
, or an array of float
, and you wanted to multiply every element by 2, without repeating too much code. I assume that in your actual situation, you have functions to apply that are more involved than just "multiply by 2".
If you're comfortable using function pointers, you could literally write a pair of "apply function to int" and "apply function to float" functions, with the actual do-the-work function specified separately, and exactly once. Here are the two "apply function" functions:
void apply_func_to_int(double (*func)(double), int *pSrc, float *pDst, int len)
{
for(int i = 0; i < len; i++)
pDst[i] = func(pSrc[i]);
}
void apply_func_to_float(double (*func)(double), float *pSrc, float *pDst, int len)
{
for(int i = 0; i < len; i++)
pDst[i] = func(pSrc[i]);
}
As you can see, they are very, very similar to each other — basically a copy-and-paste job — but they're both so short, the repetition isn't too objectionable.
Here is the function to apply:
double func(double x)
{
return x * 2;
}
Notice that you only have to write this function once. It accepts and returns a double
, for reasonably full generality.
Putting it all together:
int main()
{
int i;
int input[3] = { 1, 2, 3 };
float output[3] = { 0 };
apply_func_to_int(func, input, output, 3);
for(i = 0; i < 3; i++) printf("%f ", output[i]); printf("\n");
float input2[3] = { 1.1, 2.2, 3.3 };
apply_func_to_float(func, input2, output, 3);
for(i = 0; i < 3; i++) printf("%f ", output[i]); printf("\n");
}
And of course you can apply other functions:
#include <math.h>
/* ... */
float input3[4] = { 2, 10, 25, 1.44 };
apply_func_to_float(sqrt, input3, output, 4);
for(i = 0; i < 4; i++) printf("%f ", output[i]); printf("\n");