tags:

views:

233

answers:

12

I have grep function in C( embedded programming ) that takes a void pointer as a parameter. the function needs to be able to handle different kinds of types of variables like chars ints and longs. How can I code the function so it can figure out by itself what type of variable i am passing ?? I dont know if this is possible. thanks

ie.


void grep( void *t ) 
{ 
   if( t == char ) 
   { 
      do this 
   } 
   if( t == int ) 
   { 
      do that  
   }  
   ... 
}
+8  A: 

It is not possible to do with any accuracy. A 4 byte integer could easily be interpreted as a string for example. For example, a null terminated string "ABC" would be the same as the integer value 1094861568 (depending on byte order).

Mark Wilkins
Thank you that answers my question.
jramirez
If this answers your question, please click on the check mark.
Thomas Matthews
yeah I got the answer really fast :) so I couldnt click the check mark for 10 minutes. love SO !
jramirez
+3  A: 

That is not possible in C. You will have to indicate the intended type of the parameter explicitly. You will have to pass a second argument or pass a union or struct which has the type information as parameter.

Rajorshi
+3  A: 

Void pointer contains just a location in memory where the piece of data is stored. You can't infer any type information from it. But what you can do is, pass two parameters to your function one for the type and another for the pointer.

If you can use C++ you can create a set of overloaded helper functions that will supply the type type information.

Vlad
A: 

As Mark points out, it's not possible, but you could make overloaded versions for the types you're expecting.

Edit: Correction, you could create similar functions to handle the different types:

void grep_c( char *t ) 
{ 
    do this 
}

void grep_i( int *t ) 
{ 
    do that  
}

I've been writing too much C++ recently!

Jon Cage
C has no overloading.
GMan
C does not support overloading.
Rajorshi
Your "edited" and "updated" solution defies the whole point of checking types at runtime. The client code will have to hand pick your functions before compilation.
bits
@bits: See anand.arumug's answer if calling separate functions is such a pain: http://stackoverflow.com/questions/3198702/c-void-pointer-question/3198826#3198826 ...but you can't overload in C as several people pointed out.
Jon Cage
+1  A: 

The only way i can think of is to either pass the type as a second parameter, or have a struct with the pointer and an enum or something specifying the type, and pass that instead of a naked pointer. C doesn't have built in metadata like .net and Java do, or even an equivalent to RTTI that i'm aware of.

cHao
+1  A: 

I think you'll find this is not possible in C.

C++ has templates and overloading which are a nice solution to this sort of problem.

In plain old C you would simply write a different function for each type you need to handle.

Macros are another option in C, but consider whether its is worth the effort and confusion it may cause other developers.

saille
+1  A: 

This kind of multi-role function is not a recommended approach as it's hard to catch programming errors and debug. I suggest making separate grep functions for each argument type and have these call helper functions for any shared grep code logic.

If you must pass around typeless objects to functions then I suggest you wrap them in a struct which adorns them with a type. Something like:

struct {
    enum TYPE { INT, CHAR, STRING } type;
    void *object;
}
bjg
A: 

If you know the types that you will be handling before hand, then you can define a grep function for each type like:

grep_int(int* pi);
grep_char(char* pc);
grep_float(float* pf);

Also define a macro like

#define GREP(T, TPTR_VAR) grep_##(TPTR_VAR)

So a call like GREP(int, pi) will get translated to grep_int(pi)

anand.arumug
You made a typo. Should be `grep_##T(TPTR_VAR)`
Chris Lutz
Don't you think the client code will have to know the types before compiling the code?
bits
What I meant by saying "if you know the types before hand" is, if the author of this grep code is the sole user, then yes the client code will know the types before compiling the code. Otherwise, if you try to use the GREP macro like GREP(MyStruct, ptr_to_my_struct) then it won't work unless the user has the knowledge that a grep_mystruct() has to be implemented.
anand.arumug
@Lutz thanks for correcting the typo.
anand.arumug
+1  A: 

You're basically asking how to do introspection in C. Unfortunately this is not a supported feature.

Instead you could use functions like grep_char as @anand.arumug pointed out. Or (if possible) you could move to C++ and make use of its function overloading features.

StackedCrooked
+1  A: 

You may want to take a look at the ioctl() function. It takes a generic pointer to memory and interprets it differently based on the request code passed to the function. You can't determine what a generic pointer points to without some sort of additional information, and the ioctl() function shows you one (relatively simple) way of doing it.

bta
+1  A: 

Direct answer: it's not possible. Also, you should avoid writing such super functions that act on multiple types 2unless you can truly generalize the code and apply polymorphism. In C, that would often involve function pointers. Otherwise, there's nothing wrong with writing multiple functions that each act on a single type. In fact, that should be preferable over super functions.

Here's a basic example (not very useful, but simple):

#include <stdio.h>

typedef int less_function(void*, void*);

struct foo
{
    int data;
};

int foo_less(void* a, void* b)
{
    struct foo* f1 = a;
    struct foo* f2 = b;
    return f1->data < f2->data;
}

int find(void* search_array, void* element, int num, int element_size, less_function* less)
{
    int j = 0;
    char* search_pos = search_array;

    for (j=0; j < num; ++j, search_pos += element_size)
    {
        // if current element == element to find
        if (!less(search_pos, element) && !less(element, search_pos) )
            return j;
    }
    return -1;
}

int main()
{
    struct foo my_array[10] = { {0}, {1}, {2}, {3}, {4}, {5}, {6}, {123}, {7}, {8} };
    struct foo search_element = {123};

    // outputs 7
    printf("%d\n", find(my_array, &search_element, 10, sizeof(struct foo), foo_less) );
}

In the above code, you can see that I don't have code like: if this type is an integer, do this, if it's a float, do that, if it's a struct foo object, do this, etc. Instead we rely on function pointers to provide the custom behavior for comparing the type of object being passed in.

qsort also does this and is a good example to look at. It's quite similar to the find function above, except its comparator doesn't simply return true/false based on whether the first object is less than the other: it's like strcmp and returns 0, -1, or +1.

+1  A: 

No its not possible.

You have to pass a additional variable to tell the funtion the type of input variable. However i think you can use the macro which is suggested above. This way you will break the function grep into 3 sub-functions (if i may call them that).

Enums will be easier in case you pass any other datatype later. You can use a switch statement inside the function and perform the operations on the input data.

enum TYPE( TYPE_1, TYPE_2, TYPE_3,TYPE_MAX}; /*Add other data types into this enum if need be */

Please name the enum entries as per your requirment.

Later you can just modify the function switch case and add a additional case to it.

Praveen S