void* question

J

Janet

What is the major reason for using void*?
When should we use void* for both input arguments and return value?
How can we cast the void* pointer to the type we need?
Thanx
 
M

Malcolm McLean

Janet said:
What is the major reason for using void*?
When should we use void* for both input arguments and return value?
How can we cast the void* pointer to the type we need?
Thanx
Take a proposed addition to the standard library.

void memswap(void *ptr1, void *ptr2, size_t len)

it simply exchanges two areas of memory.
So to swap two integers we would write

int i, j;
memswap(&i, &j, sizeof(int));

to exchange two doubles

double x, y;
memswap(&x, &y, sizeof(double));

and so on.

The void * parameters mean we don't need ugly casts. Internally, however,
memswap will handle the pointers as unsigned char *s. It doesn't need to
understand what it swaps, it just sees two areas of memory.
 
B

Ben Pfaff

Janet said:
What is the major reason for using void*?

A pointer to void is often used when the type of data that a
pointer points to is unknown at compile time.
When should we use void* for both input arguments and return value?

When the above is true about input arguments and return values.
How can we cast the void* pointer to the type we need?

There is rarely a need to cast a pointer to void, because most
conversions from a pointer to void to a pointer to another object
type can take place implicitly, but the syntax is no different
from that for any other cast.
 
E

Eric Sosman

Janet said:
What is the major reason for using void*?

To deal with a pointer when the type of the thing
it points to is unknown or unimportant. For example,
the malloc() function allocates memory but does not
know or need to know what kind of data you intend to
store in it.
When should we use void* for both input arguments and return value?

As above.
How can we cast the void* pointer to the type we need?

With a cast operator, like `(int*)ptr' or `(char*)ptr'.
Since the void* pointer carries no information about the
kind of data it points to, you need some other way to
figure out which cast operator is appropriate.
 
F

Flash Gordon

Eric Sosman wrote, On 10/02/08 21:49:
Janet wrote:


With a cast operator, like `(int*)ptr' or `(char*)ptr'.
Since the void* pointer carries no information about the
kind of data it points to, you need some other way to
figure out which cast operator is appropriate.

More often than not you should not cast the pointer at all. This is
because it is implicitly converted when assigned to a variable of
another type. So Janet should *not* cast the result of malloc.
 
T

Tomás Ó hÉilidhe

Janet:
What is the major reason for using void*?
When should we use void* for both input arguments and return value?
How can we cast the void* pointer to the type we need?
Thanx


A void* is really just a char* that has few more "features" (...or even
"lack of features").

The differences between char* and void* are:
1) void* has implicit conversion to and from every other pointer type.
2) You can do pointer arithmetic on a char*, but NOT on a void*.
3) You can dereference a char*, but not a void*.

Basically the idea is that you use a void* when you aren't certain what
you're going to be pointing to. You might be pointing to an int one minute,
then a double the next.

At the end of the day tho, both void* and char* really just store the
address of a byte.
 
J

Jack Klein

Eric Sosman wrote, On 10/02/08 21:49:

More often than not you should not cast the pointer at all. This is
because it is implicitly converted when assigned to a variable of
another type. So Janet should *not* cast the result of malloc.

More correctly, pointer to void is implicitly converted by assignment
to a pointer to any object type. It is not implicitly converted, nor
is there a defined cast, from pointer to void to any arithmetic type,
aggregate type, or pointer to function.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
J

Janet

More correctly, pointer to void is implicitly converted by assignment
to a pointer to any object type. It is not implicitly converted, nor
is there a defined cast, from pointer to void to any arithmetic type,
aggregate type, or pointer to function.

Could you say what you mean by "no defined cast to pointer to function"?

Maybe I should elaborate on the question. Basically I'm coming from JAVA
and trying to implement polymorphism via an array of function pointers.

The functions all take the same arguments, but they have different
return values, e.g.
int f1(int x, int y);
double f2(int x, int y);
etc.

As I'm never actually going to need the return value I was hoping to use
a void* instead of actual function pointers to let me ignore the
difference between the return types of the functions. Is that going to
work?
 
M

Malcolm McLean

Janet said:
The functions all take the same arguments, but they have different
return values, e.g.
int f1(int x, int y);
double f2(int x, int y);
etc.

As I'm never actually going to need the return value I was hoping to use
a void* instead of actual function pointers to let me ignore the
difference between the return types of the functions. Is that going to
work?
You need wrapper functions

void F1(int x, int y)
{
gf(x, y);
}

void F2(int x, int y)
{
f2(x, y);
}

Now you can have a list of

typedef void (*fptr)(int x, int y);

fptrs (function pointers) to select the appropriate function.
 
B

Ben Bacarisse

Janet said:
Could you say what you mean by "no defined cast to pointer to
function"?

He means that converting between what is often called a "data pointer"
(a pointer to any arithmetic or aggregate type) and a function pointer
is not permitted by the standard. Such a conversion is often provided
as an extension, but it is not wise to rely on it.
Maybe I should elaborate on the question. Basically I'm coming from JAVA
and trying to implement polymorphism via an array of function pointers.

The functions all take the same arguments, but they have different
return values, e.g.
int f1(int x, int y);
double f2(int x, int y);
etc.

As I'm never actually going to need the return value I was hoping to use
a void* instead of actual function pointers to let me ignore the
difference between the return types of the functions. Is that going to
work?

No, not a void * because of the above.

You may, however, convert between and two function pointer types but
at the point of making the call, the type of the pointer used must
match that of the function being called.

You can legally do this:

typedef void generic_function(int, int);
generic_function *fp1 = (generic_function *)f1;

provided that when you call the pointer to function you convert the
pointer:

((int (*)(int, int))fp1)(4, 2);

This is, of course, rather ugly (some typedefs help) but, worse,
you've got to know the type at the point of call and that can defeat
the purpose.

So, to avoid this, you have to have the functions returning the same
type. You can do this by wrapping them as Malcolm McLean has
suggested. An alternative is to edit them so they all return a union
type which includes all the possible old return types. The down side
of this method is that you may have existing calls like:

int x = f1(2, 3);

that need to be changed to:

int x = f1(2, 3).int_value;

but you will not have a whole bunch of extra wrappers. Of course, if
you *really* don't need the return value, just loose it and make all the
function return void.

The union return is a royal pain in "old" C90. In C99 one has compound
literals and one can write:

typedef union value_t {
int int_value;
double double_value;
} value_t;

value_t f1(int x, int y) { return (value_t){ .int_value = x + y }; }

One of the best parts of C99 IMHO.
 
T

Tomás Ó hÉilidhe

Janet:
Maybe I should elaborate on the question. Basically I'm coming from
JAVA and trying to implement polymorphism via an array of function
pointers.


Rather than an array of function pointers, we simply have a struct
containing different kinds of function pointer, reason being that we
have the freedom to specify different return values and arguments for
each of the functions.

The functions all take the same arguments, but they have different
return values, e.g.
int f1(int x, int y);
double f2(int x, int y);


Yes, see, here is your problem. You should use a struct instead.

Imagine you had the following in Java:

(I don't actually know Java so I'm going to write C++ code, but
hopefully you'll get the idea)

class BaseClass {
public:

virtual void Speak(void) { WriteToScreen("I like ice-cream"); }
virtual double GetValue(void) { return 7.2; }
};

class Derived1 : BaseClass {
public:

virtual void Speak(void) { WriteToScreen("I like custard"); }
virtual double GetValue(void) { return 2.44; }
};

class Derived2 : BaseClass {
public:

virtual void Speak(void) { WriteToScreen("I like jelly"); }
virtual double GetValue(void) { return 63.8; }
};


If we wanted to implement this in C, then we'd have:


struct VTable {
void (*const Speak)(void);
double (*const GetValue)(void);
};

struct BaseClass {
VTable const *const pvt;
};

struct Derived1 {
VTable const *const pvt;
};

struct Derived2 {
VTable const *const pvt;
};

Then, if you wanted to invoke Speak on an object, you'd do:

void ExploitPolymorphism(Derived2 *const p)
{
p->pvt->Speak();

p->pvt->GetValue();
}


(And yes, the methods I've written should of course have been declared
const, but I left it out so as not to clutter things).
 
P

Peter 'Shaggy' Haywood

Groovy hepcat Tomás Ó hÉilidhe was jivin' in comp.lang.c on Mon, 11 Feb
2008 11:17 am. It's a cool scene! Dig it.
Janet:


A void* is really just a char* that has few more "features" (...or
even "lack of features").

Wrong, I'm afraid. A void * is not a char * at all. Although they do
have the same size and representation, this does not make them the same
thing, by any means.
The differences between char* and void* are:
1) void* has implicit conversion to and from every other pointer type.

Wrong again. void * has implicit conversion to and from every pointer
to object and incomplete type, but not pointer to function type.
 
T

Tomás Ó hÉilidhe

Peter 'Shaggy' Haywood:
Although they do have the same size and representation, this does not
make them the same thing, by any means.


Same size and representation is good enough for me -- they're the same
thing just with a different interface to the programmer.

void * has implicit conversion to and from every pointer
to object and incomplete type, but not pointer to function type.


Nice catch, thanks for the correction.
 
I

Ian Collins

Tomás Ó hÉilidhe said:
Peter 'Shaggy' Haywood:



Same size and representation is good enough for me -- they're the same
thing just with a different interface to the programmer.
Try dereferencing them and see what you get...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top