views:

1945

answers:

6

i have a function like

void printMe (void *i)
{
    printf("%d", i);
}

where i want to pass a void pointer and print it to screen. The above example is fine if the i is integer, float or double but crashes if i is a char. There is no overloading in C like i usually use in C++. So the question is this, can we create a function in C that will print the element that is it's parameter, and if yes how is this possible because it totally eludes me at this moment.

+14  A: 

Q1: So the question is this, can we create a function in C that will print the element that is it's parameter

A: Not in the way you want. You will have to pass information to the function, telling it the type of data you're passing.

Q2: and if yes how is this possible because it totally eludes me at this moment.

A: It's eluding you because it can't be done. There is no metadata associated with a void* that the compiler or runtime can use to figure out they type it's pointing to. You need to either

  1. pass a structure that contains a
    pointer and information about what
    the pointer points to (e.g. an enum).
  2. pass an extra parameter with information about what the pointer points to

As the code stands the only thing you can print here is the address that i points to.

A void pointer points to raw data, printf assumes you know what data type you're printing, it has no intelligence and cannot "figure it out" for you.

It's that simple.

What you can do is pass type information to the function, but then you end up with something very like printf it's self, where you pass a formatting string containing type information about the data in the following arguements.

Hope this helps.

Also . . . "There is no overloading in C like i usually use in C++"

Even in c++ the overloading happens at compile time, and here there's no way for the compiler to know what data will be passed to that function, so even though you're used to overloading, it would never work like this (e.g. try this same thing using printf, but compile it with a C++ compiler, you'll get exactly the same results). Actually try

cout << i;

in the function above, and it will give you the address i points to, not the "value" of i. You'd need to cast i and derference it before you could get it's value

cout << *(int*)i;

So, to get the above working in C++ you'd need to have lots of overloaded functions (or a template function, which is really the same thing, except the compiler rolls the functions for you) e.g. overloaded functions

printMe(int i){...}
printMe(double d){...}
printMe(char c){...}
printMe(char* string){...}

In c you just need to give those functions specific names

printInt(int i){...}
printDouble(double d){...}
printChar(char c){...}
printString(char* string){...}
Binary Worrier
And if you feel yourself inclined to macro tricks: #define printMe(x,y) print##x(y)to be use as: printMe(Int,pippo); printMe(Char,pluto);with no real benefit over the original version except that one can pretend it's using just a single function "printMe()".
Remo.D
Be careful, because as far as I'm aware those macro tricks are vendor specific (MS to be precise). If I'm wrong can someone add a comment saying so? Thanks
Binary Worrier
The ## concatenation operator is part of the basic C preprocessor spec.
Crashworks
also there are few libraries built using these macro tricks - pretending function overloading. worth looking at tgmath.h for example ...
FL4SOF
A: 

Well, since your printf is set to always print an integer, why not simply pass an int into your function instead of a void*?

Crashworks
+3  A: 

For a start, you're printing the pointer, not what it points to. To print the actual contents, you need to pass *i to printf, not i.

If you really want to do this, one solution is:

void printMe (void *p, int typ) {
    switch(typ) {
        case TYP_INT: printf("%d", *((int*)p)); break;
        case TYP_CHR: printf("%c", *((char*)p)); break;
        /* and so on ... */
    }
}
paxdiablo
Well, that depends on what you pass as the first parameter to printf. If you pass %s it will try to print what the void pointer points to.
Binary Worrier
... but actually I see what you're saying, it makes sense in the context of the question. Forgive me, I'm not fully awake yet ...
Binary Worrier
+1  A: 

So the question is this, can we create a function in C that will print the element that is it's parameter

Yes, we can. Such a function is already part of the standard library - it's called printf ;)

As there is no compile-time function overloading in C, you somehow have to supply the type of the arguments at runtime. The printf format string can be used to do this, so there's really no reason to build your own wrapper function when there's already a working solution.

Christoph
yes but my problem is that i don't know what i will be before run time so i have declared it void *. no answer helped until now
I'm confused by you're comment: `printf` already can take arguments of any type; and there is no way around knowing the type of your variable before calling any print function you might implement yourself: how else to know how to print the value?
Christoph
+1  A: 

If you are trying to print out the pointer value, the correct usage is printf("%p", i);. The 'd' specifier is for integers, and the 'p' is for pointers. It's your responsibility to get these correct, and bad things can happen if you mix them up.

I don't know why this would fail for a char * and not an int *, and it is possible you've got other problems causing this. If it still fails with %p, something else got messed up. See if you can install some sort of memory monitor software to check for dangling pointers or double free()s, because at that point the smart money's that you've corrupted memory somewhere.

David Thornley