======
1st paste:
steve wrote:
> Hey guys,
> I have a delemna which I can't figure out.
> This is regarding "void pointers" and I confess, I really don't
> understand them nearly enough to even understand what the problem is.
A void pointer is an address of a region of memory (which may or may not
be occupied). It is an error to attempt to use a void value in an
expression, hence why compilers will often warn you if you dereference a
void pointer.
(Note to the regulars: I'm probably not being perfectly accurate here,
but I don't think c.l.c pedantry is what steve needs)
(Note to steve: the correct spelling is dilemma)
> void * params[5];
This creates an array of 5 pointers to void. It does not create an
array of "void" (as you seem to think).
> int int_param_values[5] = {1,2,3,4,5};
> char **str_param_values;
> str_param_values = malloc(5 * sizeof(char *));
> str_param_values[0] = malloc(10 * sizeof(char));
> strcpy(str_param_values[0], "hello");
> double dbl_param_values[5] = {1.1, 2.2, 3.3};
This creates an array of int, an array of char *, and an array of
double, and initialises them in various ways.
Note two things: firstly, it would probably make more sense for
str_param_values to be an array of 5 char *, and allocated on the stack,
with
char *str_param_values[5];
There is no obvious need for it to be on the heap.
Secondly, you have not tested the return value of malloc() in either of
these calls; I realise this is only example code (incidentally, you will
get more informative answers if you post actual code; then we know what
you're trying to achieve!) but nonetheless it bears pointing out.
> I can then assign my data values, to the array,
> like so:
> params[indx] = (void*)int_param_values[ndx];
This is casting an int to a void *. This is generally incorrect as an
int is not a pointer type. It just so happens that you are, IIRC,
allowed to do this by a special provision to allow the use of integer
expressions as pointers. In this case this is clearly not what you are
doing as, for instance, params[0] is now (void *)1; this is now a
pointer to the memory with address 1, which probably isn't even mapped
in your program's address space (if you're on a memory managed
architecture. On, say, an embedded system you might want to do this).
> params[indx] = (void*)str_param_values[ndx];
This is casting a char * to a void *. This is allowed because both are
pointer types. params[indx] now points to the first character of
str_param_values[ndx].
> These two methods compile just fine and work as expected.
> However, this statement will not compile:
> params[indx] = (void*)dbl_param_values[ndx];
This is casting a double to a void *. This is not allowed; a double is
not the same size as, nor anything like, a void *. Unlike an int it
cannot even reasonably be interpreted as an address; what location in
memory would (void *)0.5 point to? It's just silly really!
> and generates this compiler error:
> "...cast from 'double' to 'pointer to void' is illegal"
Quite right too.
> When it's all said and done, the idea is to pass the data referred to
> in the array as function parameters,
> like so:
> MyFunction(params[0], params[1], etc.);
There are two appropriate methods I can think of. One is to use
varargs; if the function's first argument gives it some way of deducing
the types of the remaining arguments, it can do so. This is for
instance how the *printf() family of functions work.
The other is to use void *, but populate it not with the data themselves
but with pointers to them; for instance your doubles would become
something like:
params[indx] = (void *)&dbl_param_values[ndx];
where we assign the /address/ of the double to the pointer; we are now
casting a double * to a void *, which makes much more sense as both are
pointer types.
One question I do have: given your function prototype as you have it,
where the only arguments are the params[] elements, how does the
function know to what the pointers refer (i.e., whether you have used an
int, a double, a char *, or whatever).
If, of course, it is simply, say, printing their addresses, it need not
know; but if it is using their values, it will have to be told, since
not only does it not know their true types, it doesn't even know their
sizes, and a pointer without size information is not much use.
Note also that you cannot make an array of void and store the values
(ints, doubles etc.) in that, because void has no storage size.
Perhaps the real solution to your problems, however, is to use a struct
or union.
I can't really give any more specific advice without some information as
to what you're trying to achieve.
-Edward
==========
2nd paste:
Hey Ed,
thanks for your indepth reply.
Very helpful.
> (Note to steve: the correct spelling is dilemma)
Sorry for that.
I'm one of those people prone to typos and misspelling.
I should have run spell check, I usually do.
> > void * params[5];
> This creates an array of 5 pointers to void. It does not create an
> array of "void" (as you seem to think).> int int_param_values[5] = {1,2,3,4,5};
No, I get that.
My understanding was that it was creating an "array of 5 pointers to
void".
Which I then intended to populate with the addresses of the variables.
> Note two things: firstly, it would probably make more sense for
> str_param_values to be an array of 5 char *, and allocated on the stack,
> with
> char *str_param_values[5];
Actually, I did try that.
It did not produce the result I was hoping for.
> This is casting a double to a void *. This is not allowed; a double is
> not the same size as, nor anything like, a void *. Unlike an int it
> cannot even reasonably be interpreted as an address; what location in
> memory would (void *)0.5 point to? It's just silly really!
Clearly I'm wrong here, but, I was making the 'assumption' that a
"pointer to void" was just that,
a pointer to the address of a variable of an undertermined type.
Regardless of the size of the variable.
On a given system, are not addresses the same size ?
What I'm after here, is a "generic" mechanism for holding addresses of
mixed variable types.
i.e.: an array of addresses.
Be they of type int, or char, or double, etc.
What I'm (really) after here is to construct a 'generic mechanism' for
calling functions within DLLs at RunTime.
These DLLs, their Functions and Parameters passed are not known at
compile time.
Research indicated that void pointers was the way to do this.
Suggestions ?
Steve
==========
3rd paste:
steve wrote:
>> Note two things: firstly, it would probably make more sense for
>> str_param_values to be an array of 5 char *, and allocated on the stack,
>> with
>> char *str_param_values[5];
>
> Actually, I did try that.
> It did not produce the result I was hoping for.
Curious. It certainly should have.
>> This is casting a double to a void *. This is not allowed; a double is
>> not the same size as, nor anything like, a void *. Unlike an int it
>> cannot even reasonably be interpreted as an address; what location in
>> memory would (void *)0.5 point to? It's just silly really!
> Clearly I'm wrong here, but, I was making the 'assumption' that a
> "pointer to void" was just that,
> a pointer to the address of a variable of an undertermined type.
> Regardless of the size of the variable.
> On a given system, are not addresses the same size ?
Your assumption is valid; the problem is that you weren't putting a
pointer to the double into the void *, you were trying to put the double
itself into the void *. As mentioned elsewhere in the thread, the '&'
operator is what you're looking for.
> What I'm after here, is a "generic" mechanism for holding addresses of
> mixed variable types.
> i.e.: an array of addresses.
> Be they of type int, or char, or double, etc.
> What I'm (really) after here is to construct a 'generic mechanism' for
> calling functions within DLLs at RunTime.
> These DLLs, their Functions and Parameters passed are not known at
> compile time.
> Research indicated that void pointers was the way to do this.
Firstly, I can't think of a good reason why you would want to do this.
It sounds as though you've come up with some idea for a 'generic
mechanism' without actually having any use cases in mind.
Besides, linking against ill-defined interfaces is a bad idea. If
you're trying to define functionality at runtime, an embedded scripting
language is the way to go.
But if you /really/ want this, void pointers will do it - but you have
to remember that what you assign to the void pointer has to, itself, be
a pointer too (hence why your double to void * cast wasn't valid). Also
remember that if you pass a pointer, the callee can modify the
referenced object. This may not be what you want.
What it /really/ sounds like is that you want function overloading
and/or dynamic types - in other words, you're trying to make C more like
C++ or Java. From my perspective that seems like a silly thing to do:
why would you want C++ in the first place - and if you do, you know
where to find it ;)
-Edward
==========
BTW, the website of Edward is worth viewing.

