Question

#include<stdio.h>
void fun(void *x)
{
    //what is the data type of 'x', since I could have passed float instead of 
    //  int so first I have to check datatype of this and then proceed further.
}
int main()
{
     int n=10;
     fun(&n);
}

You can see that we dont know the type of 'x' in function fun() so how could we find out that without using(passing) any other information in function argument?

Was it helpful?

Solution

C11 has type-generic expressions to help you solve this problem. You could do something like this example:

#define myFunction(X) _Generic((X), \
    int *:   myFunctionInt,         \
    float *: myFunctionFloat,       \
    default: myFunctionInt          \
    )(X)

void myFunctionInt(int *x);
void myFunctionFloat(float *x);

And then call it the way you are:

int n = 10;
myFunction(&n);

or:

float n = 10.0f;
myFunction(&n);

You will need to implement the separate target functions, but you could just do the pointer magic there and pass off to a common handler, for example.

OTHER TIPS

C does not have runtime type information. When you pass a pointer, then you pass a naked pointer - a memory address.

If you are using pointers to void but need to know the type, then you have to pass some additional information. Otherwise, you create different functions for different types, like foo that expects an int, dfoo that expects a double and so on.

You cannot know the type when you cast to a void *. You have to be careful while using a void pointer, because you can cast it to any type. That is the purpose to have a void pointer.

C does not allow to get the type of the variable passed by void*. The only thing, that you can do it is write kind of object oriented code by your self.

Probably something like this:

typedef struct generic_type_s 
{
    void* data;
    void  (*f)(void* data);
} generic_type_t;

void f_int(void* _data)
{
    int* data = (int*)_data;
    // Do something
}

int main()
{
   int data1 = 10;
   // Generic variable initialization
   generic_type_t gv;
   gv.data = &data1;
   gv.f = f_int;

   // Calling an appropriate function
   gv.f(gv.data);

   return 0;
}

The C way of doing this is using a tagged union:

typedef enum {
    // will default to TypeUnitialized if unspecified in structure initializer
    TypeUninitialized = 0,
    TypeFloat = 1,
    TypeInt
} type_t;

typedef struct {
    type_t type;
    union {
        int u_int;
        float u_float;
    };
} gen_val_t;

void fun(gen_val_t v)
{
    switch (v.type) {
    case TypeFloat:
        // process float
        break;
    case TypeInt:
        // process int
        break;
    default:
        // error
        break;
    }
}

int main(int argc, char **argv)
{
    gen_val_t ov = { .type = TypeFloat,
                     .u_float = 3.45 };
    fun(ov);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top