[comp.lang.c] "void **" : Is it valid and what does it mean?

aj3u@jade.cs.virginia.edu (Asim Jalis) (05/28/91)

I want to write a function that takes as arguments pointers to
pointers to any type.  As in,

func(void **p)
{
...
}

main()
{
  int *i;
  float *f;
  char *c;

  func(&i);
  func(&f);
  func(&c);
}

However, the compiler gives me warnings about incompatible type for
all the function calls.  The code itself works fine, but I was
wondering if somehow I could also get rid of the warnings, perhaps by
doing this in a more elegant way.

Basically what I want is a type that would coerce to a pointer to a
pointer to a type, for any type.  Sort of one level beyond simple
"void *".

Any help would be appreciated.

Asim Jalis.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (05/28/91)

Yes, void ** is valid, and it means pointer-to-generic pointer.
Note that void ** itself may be represented some other way entirely;
void ** is not itself a generic pointer.

In article <AJ3U.91May27213633@jade.cs.virginia.edu>, aj3u@jade.cs.virginia.edu (Asim Jalis) writes:
> func(void **p)
> { ... }
> 
> main()
> { int *i; float *f; char *c;
> 
>   func(&i); func(&f); func(&c);
> }
> 
> However, the compiler gives me warnings about incompatible type for
> all the function calls.

The compiler is RIGHT.  You promised it (oh, you deceiver) that
you would give func() pointers to generic (void*) pointers
(call the representation of generic pointers REPRESENTATION 0)
But you lied (oh, you scoundrel, you).  You gave it
    -- a pointer to (a pointer to int  -- REPRESENTATION 1)
    -- a pointer to (a pointer to float -- REPRESENTATION 2)
    -- a pointer to (a pointer to char -- REPRESENTATION 0)
char* and void* use the same representation.
But void*, int*, and float* need not even be the same _size_, let
alone use the same physical representation.

> The code itself works fine,

no, there is a bug in there, waiting, like a blood-sucking insect
poised on a bush waiting for a deer to pass by, for an opportunity to bite.

> Basically what I want is a type that would coerce to a pointer to a
> pointer to a type, for any type.  Sort of one level beyond simple
> "void *".

Why do you want to do _that_?  If you _could_ do it, you would be
throwing away information that the receiver would need in order to
be able to _use_ the thing?  What's the context?

-- 
Should you ever intend to dull the wits of a young man and to
incapacitate his brains for any kind of thought whatever, then
you cannot do better than give him Hegel to read.  -- Schopenhauer.

hp@vmars.tuwien.ac.at (Peter Holzer) (05/28/91)

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:

[...good explanation why void ** isn't a pointer to any pointer
deleted...]

>> Basically what I want is a type that would coerce to a pointer to a
>> pointer to a type, for any type.  Sort of one level beyond simple
>> "void *".

>Why do you want to do _that_?  If you _could_ do it, you would be
>throwing away information that the receiver would need in order to
>be able to _use_ the thing?  What's the context?

I don't know what the original poster wanted to do, but since I was in
the same situation once, I can give you an example why anybody would
like to do something like that.

In MARS (a real-time system developed at our department) exists a
system-call which is now defined as:

int receivem (msg_name name, void * msg, unsigned short flags);

Messages are (in C) defined as structures and there are several types.
For some reason, which is not relevant here, msg is not a pointer to
the structure, but a pointer to a pointer to structure. Of course one
common error is to define a struct foo * mymsg and then pass mymsg
instead of &mymsg. With the current prototype this error is not
detected by the compiler, but if some type `pointer to any pointer'
existed, this type of error could be catched. Unfortunately this is not
possible in C.

#pragma speculation_mode on	/* :-) */
There is a rumor among C-programmers that `all struct-pointers smell
the same.' (I could not find any assertion of this in the standard, and
I can find pro's and con's for such a rule, so I call it a rumor,
undoubtedly someone who knows will tell me if it is correct or not). If
this rumor is true, a pointer to pointer to any struct would be legal
(At least there is no reason why it should not be legal). So we could
declare the systemcall above as:

int receivem (msg_name name, struct ** msg, unsigned short flags);

which is almost exactly what the designer of the system call had in
mind.
--
|    _  | Peter J. Holzer                       | Think of it   |
| |_|_) | Technical University Vienna           | as evolution  |
| | |   | Dept. for Real-Time Systems           | in action!    |
| __/   | hp@vmars.tuwien.ac.at                 |     Tony Rand |

gwyn@smoke.brl.mil (Doug Gwyn) (05/29/91)

By the way, there is no need to go through a lot of gyrations to attain
the originally-stated goal.  Just declare the parameter as a void * anyway,
and apply the appropriate cast inside the function where it is used.  E.g.
	void foo(void *param) { ++(*(struct msg **)param)->field; }
After all, the thing pointed to, in this case a "struct msg *", is also an
object and so a pointer to it (a "struct msg **") can be fairly
conveniently converted to void* and back.

wittig@gmdzi.gmd.de (Georg Wittig) (05/29/91)

hp@vmars.tuwien.ac.at (Peter Holzer) writes:

>[...good explanation why void ** isn't a pointer to any pointer

>>Why do you want to do _that_?

>For some reason, which is not relevant here, msg is not a pointer to
>the structure, but a pointer to a pointer to structure. Of course one
>common error is to define a struct foo * mymsg and then pass mymsg
>instead of &mymsg. With the current prototype this error is not
>detected by the compiler, but if some type `pointer to any pointer'
>existed, this type of error could be catched. Unfortunately this is not
>possible in C.

Why not use unions? Example:

	typedef union {	struct struct1 *p_struct1;
			struct struct2 *p_struct2;
			...
		      } my_union_t;

and pass the union address to your function:

	myfunc (&myunion);
	...
	myfunc (my_union_t *p_union){
		...
		p_union -> p_struct2 -> ...

This has the advantage that you MUST define which structures are allowed in
that context, and the compiler can check consistency. ... And you don't
need void **.
-- 
Georg Wittig   GMD-Z1.IT   P.O.Box 1240 | "Freedom's just another word
D-W-5205 St. Augustin 1	   (Germany)	|  for nothing left to lose"
email:		wittig@gmdzi.gmd.de	| (from "Me and Bobby McGee",
telephone:	(+49) 2241 14-2294	|  Janis Joplin, Kris Kristofferson)