By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,167 Members | 1,688 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,167 IT Pros & Developers. It's quick & easy.

question realted to void *

P: n/a
Guys,

Consider a function
func(void **var)
{

/* In function I need to typecast the variable var as (int **)
I mean to say, I need to access var as (int **)

}

My question is what is the better option, should I use
func(void **var) Or
func(void *var).

I think func(void *) should be fine, as we can store any type of
"pointer variable" in "void pointer variable".
void pointer variable should be big enough to hold any type of pointer
variable.

Is that correct? Or I am missing something?

And if that is correct, should we ever use void ** ?

thanks for any help/response.


Sep 16 '08 #1
Share this Question
Share on Google+
28 Replies


P: n/a
On Sep 16, 4:54*pm, "junky_fel...@yahoo.co.in"
<junky_fel...@yahoo.co.inwrote:
Guys,

* *Consider a function
func(void **var)
{

/* In function I need to typecast the variable var as (int **)
* *I mean to say, *I need to access var as (int **)

}

My question is what is the better option, should I use
func(void **var) *Or
func(void *var).

I think func(void *) should be fine, as we can store any type of
"pointer variable" in "void pointer variable".
void pointer variable should be big enough to hold any type of pointer
variable.

Is that correct? Or I am missing something?

And if that is correct, should we ever use void ** ?

thanks for any help/response.
You can cast anything to anything you want, but the less confusing you
can make it, the better. Ideally, func() would take an "int** var" if
that is what it really is. However, sometimes, as appears to be true
in this case, it is necessary to use void. If you need to use void,
then I would still prefer "void**" if what you are passing really is a
pointer-to-pointer.

To me what matters more than how you cast "var" inside the function,
is what the function signature tells the client caller. If I'm going
to call a function with a signature "func(void*)" then I expect to
pass a pointer, not a pointer-to-pointer. For example:

void f1(void*);
void f2(void**);

int x = 0;
int* px = &x;

f1(px); /* pointer */
f2(&px); /* pointer to pointer */

Adam
Sep 16 '08 #2

P: n/a
ju**********@yahoo.co.in wrote:
Guys,

Consider a function
func(void **var)
{

/* In function I need to typecast the variable var as (int **)
I mean to say, I need to access var as (int **)

}

My question is what is the better option, should I use
func(void **var) Or
func(void *var).

I think func(void *) should be fine, as we can store any type of
"pointer variable" in "void pointer variable".
void pointer variable should be big enough to hold any type of pointer
variable.

Is that correct? Or I am missing something?
It's not certain, because you've told us how you intend to
do something but not what you're trying to do. The answer to
"Should I use a screwdriver or a hammer?" depends greatly on
whether you're trying to drive a screw, hammer a nail, or apply
paint ...

Perhaps what you're missing is that pointers of different
types aren't interchangeable -- that is, you've not understood
question 4.9 in the FAQ. But it's hard to be sure, based on
your rather sketchy description of your goals.
And if that is correct, should we ever use void ** ?
I'll ignore everything up through the comma, because there's
not enough information to evaluate it. As for the rest, void**
crops up rather rarely, but does sometimes make sense.

--
Er*********@sun.com
Sep 16 '08 #3

P: n/a

<ju**********@yahoo.co.inwrote in message
>
And if that is correct, should we ever use void ** ?
A void ** is for a list of pointers to arbitrary memory buffers.
A void * is for a pointer to an arbitary memory buffer.

Since arbitrary memory buffers can contain lists of pointers, you can always
use a void *, just as you could for any other type.

So the question is really, "should all parameters be passed as void *'s?"

The answer is no. Only occasionally does it make sense to hide the type of
pointer from the calling function. Use of actual types enables checking in
the compiler, and is easier to read.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Sep 16 '08 #4

P: n/a
"ju**********@yahoo.co.in" <ju**********@yahoo.co.inwrites:
[...]
And if that is correct, should we ever use void ** ?
void* can be used as a generic pointer type. What that means is that
a value of any pointer type (other than a pointer-to-function type)
can be converted to void* and back again without loss of information.

You might think that void** is therefore a generic pointer-to-pointer
type, but it isn't; in fact, there is no generic pointer-to-pointer
type.

You can convert an int*, or an int**, or an int***, or ... to void*
without loss of information -- except that you lose the type
information, which you have to carefully keep track of yourself.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 16 '08 #5

P: n/a
Malcolm McLean wrote:
<ju**********@yahoo.co.inwrote in message
>And if that is correct, should we ever use void ** ?

A void ** is for a list of pointers to arbitrary memory buffers.
A void * is for a pointer to an arbitary memory buffer.
No, a void** is for a pointer to a void*. When an array of void*
is passed anywhere, the reference is made with a void**. Just the
same as any other array reference.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Sep 16 '08 #6

P: n/a
abu...@ieee.org wrote:
<junky_fel...@yahoo.co.inwrote:
* *Consider a function
func(void **var)
{
/* In function I need to typecast the variable var as
(int **)
* *I mean to say, *I need to access var as (int **)
}

My question is what is the better option, should I use
func(void **var) *Or
func(void *var).

I think func(void *) should be fine, as we can store
any type of "pointer variable" in "void pointer
variable".
You can store any pointer to an object or incomplete type.
void pointer variable should be big enough to hold any
type of pointer variable.
There is no requirement for void * to be big enough to
hold function pointers.
Is that correct? Or I am missing something?

And if that is correct, should we ever use void ** ?

You can cast anything to anything you want,
You can try. But you can also fail in the attempt.
but the less confusing you can make it, the better.
Ideally, func() would take an "int** var" if that is
what it really is. However, sometimes, as appears to
be true in this case, it is necessary to use void. If
you need to use void, then I would still prefer
"void**" if what you are passing really is a
pointer-to-pointer.
Just realise that the guarantees that go with void * are
not necessarily available to void **.
To me what matters more than how you cast "var" inside
the function, is what the function signature tells the
client caller. If I'm going to call a function with a
signature "func(void*)" then I expect to pass a pointer,
not a pointer-to-pointer. For example:

* * void f1(void*);
* * void f2(void**);

* * int x = 0;
* * int* px = &x;

* * f1(px); * */* pointer */
* * f2(&px); * /* pointer to pointer */
This violates a constraint. There is no implicit
conversion to or from void ** as there is for void *.

But even if I cast &px in the call to f2, there is no
guarantee that the conversion of &px to void ** succeeds.

Whilst unlikely in practice, the standard allows void *
to have stricter alignment than int *. In that case, the
conversion of int ** to void ** can fail.

--
Peter
Sep 16 '08 #7

P: n/a
In article
<0c**********************************@l33g2000pri. googlegroups.com>,
"ju**********@yahoo.co.in" <ju**********@yahoo.co.inwrote:
func(void **var)
{

/* In function I need to typecast the variable var as (int **)
I mean to say, I need to access var as (int **)
}

My question is what is the better option, should I use
func(void **var) Or
func(void *var).
If you have a choice, why is

void func( int** );

not an option, if that's what you're casting the argument to anyway?
That allows better type checking.
Sep 16 '08 #8

P: n/a
ju**********@yahoo.co.in said:
Guys,

Consider a function
func(void **var)
{

/* In function I need to typecast the variable var as (int **)
By "typecast" I presume you mean "cast".

If the function requires int **, pass it int ** and accept it as int **.
My question is what is the better option, should I use
func(void **var) Or
func(void *var).
void func(int **var)
I think func(void *) should be fine, as we can store any type of
"pointer variable" in "void pointer variable".
Not function pointers, but otherwise yes, provided the value is
determinate.
void pointer variable should be big enough to hold any type of pointer
variable.
With the possible exception of function pointers, yes (and broadly
speaking, this is why C doesn't guarantee that you can store function
pointers in a void *).
Is that correct? Or I am missing something?
You're missing the obvious: void func(int **var)
And if that is correct, should we ever use void ** ?
Rarely. Very rarely. It is easy to make the mistake of thinking that void
** has the same guarantees as void *, but it doesn't.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 16 '08 #9

P: n/a
>
With the possible exception of function pointers, yes (and broadly
speaking, this is why C doesn't guarantee that you can store function
pointers in a void *).
Is that correct? Or I am missing something?

You're missing the obvious: void func(int **var)
Actually, I want to typecast "var" with some structure type. Just to
keep it simple I used "int".
However, the conclusion the I make is as follows. Please correct me if
I am wrong.

1) There is nothing wrong in using "void *" (in case var is not a
function pointer).
2) Using "void **" is a better option as it is more readable and we
don't lose the pointer-type information.

thanks a lot guys..
Sep 17 '08 #10

P: n/a
ju**********@yahoo.co.in said:
>>
With the possible exception of function pointers, yes (and broadly
speaking, this is why C doesn't guarantee that you can store function
pointers in a void *).
Is that correct? Or I am missing something?

You're missing the obvious: void func(int **var)

Actually, I want to typecast "var" with some structure type.
By "typecast" I presume you mean "cast".
Just to
keep it simple I used "int".
It's always better to ask the question you mean to ask, rather than a
question that's a bit like it.

Anyway, assuming you need a struct foo **, just do:

void func(struct foo **)
However, the conclusion the I make is as follows. Please correct me if
I am wrong.

1) There is nothing wrong in using "void *" (in case var is not a
function pointer).
void * is pointless unless *either* you have a way of knowing what pointer
type is actually being passed *or* you know it doesn't matter because
you're going to treat the data as a sequence of individual bytes.

If func *only* deals with struct foo **, then pass struct foo ** and accept
struct foo **. If it deals with many pointer types (i.e. more than one)
and cannot do its job simply by treating the data as a sequence of
individual bytes, you must have some mechanism for allowing the function
to find out what type of object it is processing.
2) Using "void **" is a better option as it is more readable and we
don't lose the pointer-type information.
I don't see why void ** is more readable than void * or struct foo **, and
I certainly don't see how you can *avoid* losing information about a
structure pointer type if you convert it either to void * or to void **.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 17 '08 #11

P: n/a
ju**********@yahoo.co.in wrote:
Guys,

Consider a function
func(void **var)
{

/* In function I need to typecast the variable var as (int **)
I mean to say, I need to access var as (int **)

}

My question is what is the better option, should I use
func(void **var) Or
func(void *var).

I think func(void *) should be fine, as we can store any type of
"pointer variable" in "void pointer variable".
void pointer variable should be big enough to hold any type of pointer
variable.

Is that correct? Or I am missing something?
Any pointer to an object type can be converted to void* and back.
However, that does not mean that void* is compatible with all of those
other pointer type; it's only guaranteed to be compatible with pointers
to character types.

When you dereference a pointer, the pointed-at object has to have an
effective type that is compatible with the type pointed at by the
pointer, it can't have a type that is merely convertible to it. That's a
simplification of the real rules, but it's good enough for the purposes
of this explanation.

A void** is a pointer to a pointer to void. When you dereference it, it
has to be pointing at an actual pointer to void; it can't be pointing at
an pointer to int. int** is a pointer to a pointer to int. If you
convert an int** to a void**, dereferencing it might not work. You can't
convert it back to an int** and be sure that it compares equal to the
original pointer - that guarantee applies to void*, not void**. You
can't even guarantee that a void* has the same alignment requirements as
an int*; as a result, even the conversion of an int** to a void** could
have undefined behavior.

func(void*) is the right approach - just make sure you do it properly:

void func(void*p)
{
int **q = (int**)p;
// Use q for the real work.
}

I presume that there's some important reason why you can't simply
declare func(int **)? That would be the best approach, unless there's
something that prevents you from using it.

And if that is correct, should we ever use void ** ?
Yes, certainly:

int i;
void *p = &i;
void *arr[] = {&i, &p};

If you want to call func(&p) or func(arr), then you should declare it as
func(void**).
Sep 17 '08 #12

P: n/a
"ju**********@yahoo.co.in" <ju**********@yahoo.co.inwrites:
>>
With the possible exception of function pointers, yes (and broadly
speaking, this is why C doesn't guarantee that you can store function
pointers in a void *).
Is that correct? Or I am missing something?

You're missing the obvious: void func(int **var)

Actually, I want to typecast "var" with some structure type. Just to
keep it simple I used "int".
However, the conclusion the I make is as follows. Please correct me if
I am wrong.

1) There is nothing wrong in using "void *" (in case var is not a
function pointer).
2) Using "void **" is a better option as it is more readable and we
don't lose the pointer-type information.
Richard Heathfield has given you a detailed answer, but just in case
it helps clarify things, this question reads, to me, like this:

"I have object of type X. Is it better to use Y * or Y **?"
I.e. which of two wrong types is better? I think you are still not
asking the real question because you must be casting the pointer to
another type for some reason but we don't yet know why.

--
Ben.
Sep 17 '08 #13

P: n/a
James Kuyper <ja*********@verizon.netwrites:
[...]
Any pointer to an object type can be converted to void* and
back. However, that does not mean that void* is compatible with all of
those other pointer type; it's only guaranteed to be compatible with
pointers to character types.
[...]

I understand what you mean, but "compatible" isn't the word for it.
The standard has a very specific definition for "compatible types"; by
that definition, void* and char* are not compatible.

C99 6.7.5.1p2:

For two pointer types to be compatible, both shall be identically
qualified and both shall be pointers to compatible types.

Since void and char are not compatible, void* and char* are not
compatible.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 17 '08 #14

P: n/a
ju**********@yahoo.co.in wrote:
Guys,

Consider a function
func(void **var)
{

/* In function I need to typecast the variable var as (int **)
I mean to say, I need to access var as (int **)

}

My question is what is the better option, should I use
func(void **var) Or
func(void *var).
func(void *var)
I think func(void *) should be fine, as we can store any type of
"pointer variable" in "void pointer variable".
Yes. Moreover, that's the only option that's really "fine", as opposed
to 'void**' one.
void pointer variable should be big enough to hold any type of pointer
variable.
Yes, as long as you are talking about pointer-to-data types.
And if that is correct, should we ever use void ** ?
Hm... Yes. As well as 'void***', 'void****' and so on. Why not? The
general concept of "rising the level of indirection" is not really
related to the concept of "generic pointer type".

--
Best regards,
Andrey Tarasevich
Sep 17 '08 #15

P: n/a
Keith Thompson wrote:
James Kuyper <ja*********@verizon.netwrites:
[...]
>Any pointer to an object type can be converted to void* and
back. However, that does not mean that void* is compatible with all of
those other pointer type; it's only guaranteed to be compatible with
pointers to character types.
[...]

I understand what you mean, but "compatible" isn't the word for it.
The standard has a very specific definition for "compatible types"; by
that definition, void* and char* are not compatible.

C99 6.7.5.1p2:

For two pointer types to be compatible, both shall be identically
qualified and both shall be pointers to compatible types.

Since void and char are not compatible, void* and char* are not
compatible.
You're right: the standard requires them to have the same alignment
requirements and same representation, but they are not compatible
according to C's definition of the term. This is another of those cases
where the standard falls short of actually saying something that I think
it was actually intended to say. As a practical matter, they work just
as if they were compatible, on most implementations.

When I wrote: "That's a simplification of the real rules, but it's good
enough for the purposes of this explanation.", I should have made it
clear that this statement applied to both of the preceeding paragraphs,
not just the immediately preceding one.

Sep 17 '08 #16

P: n/a
On Wed, 17 Sep 2008 17:37:51 +0000, James Kuyper wrote:
Keith Thompson wrote:
>James Kuyper <ja*********@verizon.netwrites: [...]
>>Any pointer to an object type can be converted to void* and back.
However, that does not mean that void* is compatible with all of those
other pointer type; it's only guaranteed to be compatible with
pointers to character types.
[...]

I understand what you mean, but "compatible" isn't the word for it. The
standard has a very specific definition for "compatible types"; by that
definition, void* and char* are not compatible.

C99 6.7.5.1p2:

For two pointer types to be compatible, both shall be identically
qualified and both shall be pointers to compatible types.

Since void and char are not compatible, void* and char* are not
compatible.

You're right: the standard requires them to have the same alignment
requirements and same representation, but they are not compatible
according to C's definition of the term. This is another of those cases
where the standard falls short of actually saying something that I think
it was actually intended to say. As a practical matter, they work just
as if they were compatible, on most implementations.
My compiler reports an error when I try

void f(char *p);
void f(void *p) {}

My compiler doesn't report an error when I try

void f(void *p);
void f(void *p) {}

or when I try

void f(int (*p)[]);
void f(int (*p)[30]) {}

I have trouble believing the intent was to allow the first, or that you
believe that was intended. If char * and void * were compatible, it would
be allowed, because compatible means something different from how you are
using it.
Sep 17 '08 #17

P: n/a
James Kuyper <ja*********@verizon.netwrites:
Keith Thompson wrote:
>James Kuyper <ja*********@verizon.netwrites:
[...]
>>Any pointer to an object type can be converted to void* and
back. However, that does not mean that void* is compatible with all of
those other pointer type; it's only guaranteed to be compatible with
pointers to character types.
[...]
I understand what you mean, but "compatible" isn't the word for it.
The standard has a very specific definition for "compatible types"; by
that definition, void* and char* are not compatible.
C99 6.7.5.1p2:
For two pointer types to be compatible, both shall be identically
qualified and both shall be pointers to compatible types.
Since void and char are not compatible, void* and char* are not
compatible.

You're right: the standard requires them to have the same alignment
requirements and same representation, but they are not compatible
according to C's definition of the term. This is another of those
cases where the standard falls short of actually saying something that
I think it was actually intended to say. As a practical matter, they
work just as if they were compatible, on most implementations.

When I wrote: "That's a simplification of the real rules, but it's
good enough for the purposes of this explanation.", I should have made
it clear that this statement applied to both of the preceeding
paragraphs, not just the immediately preceding one.
Another way in which they aren't compatible is this:

int main(void)
{
char *pc;
void *pv;

char **ppc = &pc;
void **ppv = &pv;

ppc = ppv; /* constraint violation */
ppv = ppc; /* constraint violation */

return 0;
}

char* and void* can be assigned to each other, but only because
there's an implicit conversion (which, given the requirement for them
to have the same representation, will merely reinterpret the bits).

Since char* and void* are incompatible, pointers to those types are
incompatible, and cannot be assigned to each other because there is no
implicit conversion.

The standard implies that various types of type-punning between char*
and void* (and unsigned char*, and signed char*) are safe, but that
doesn't affect the many contexts that require compatible types.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 17 '08 #18

P: n/a
Harald van Dk wrote:
On Wed, 17 Sep 2008 17:37:51 +0000, James Kuyper wrote:
....
You're right: the standard requires them to have the same alignment
requirements and same representation, but they are not compatible
according to C's definition of the term. This is another of those cases
where the standard falls short of actually saying something that I think
it was actually intended to say. As a practical matter, they work just
as if they were compatible, on most implementations.

My compiler reports an error when I try

void f(char *p);
void f(void *p) {}

My compiler doesn't report an error when I try

void f(void *p);
void f(void *p) {}

or when I try

void f(int (*p)[]);
void f(int (*p)[30]) {}

I have trouble believing the intent was to allow the first, or that you
believe that was intended. If char * and void * were compatible, it would
be allowed, because compatible means something different from how you are
using it.
What I meant is a little more complicated than what I said. You can
work around the fact that those functions are incompatible by using
some type punning. The behavior of code that performs such type
punning is undefined, but I believe that it was the intent of the
committee that such type punning would work.
Sep 17 '08 #19

P: n/a
On Wed, 17 Sep 2008 13:40:16 -0700, jameskuyper wrote:
Harald van Dijk wrote:
>On Wed, 17 Sep 2008 17:37:51 +0000, James Kuyper wrote:
...
You're right: the standard requires them to have the same alignment
requirements and same representation, but they are not compatible
according to C's definition of the term. This is another of those
cases where the standard falls short of actually saying something
that I think it was actually intended to say. As a practical matter,
they work just as if they were compatible, on most implementations.

My compiler reports an error when I try

void f(char *p);
void f(void *p) {}
[snip]

What I meant is a little more complicated than what I said. You can work
around the fact that those functions are incompatible by using some type
punning. The behavior of code that performs such type punning is
undefined, but I believe that it was the intent of the committee that
such type punning would work.
The standard says "The same representation and alignment requirements are
meant to imply interchangeability as arguments to functions, return values
from functions, and members of unions." in two footnotes.

This suggests, for example, that this is valid code (and that g may be
called):

void f(void *p) {}
void g(void) {
((void(*)(char *)) f) ("Hello");
}

It doesn't actually work though, in at least gcc. But if that is really
meant to be valid, then I can agree that it is probably the intent to also
allow

void *p = 0;
char *q = *(char **) &p;
Sep 17 '08 #20

P: n/a
Harald van Dk wrote:
....
The standard says "The same representation and alignment requirements are
meant to imply interchangeability as arguments to functions, return values
from functions, and members of unions." in two footnotes.
Yes, that's precisely what I was thinking of. The problem is that it's
non-normative text. The normative text only requires same
representation and same alignment requirements. It's possible to
define function interface conventions that meet those two requirement,
while not allowing void* and char* to be interchangeable. For
instance, passing void* return values using a different register than
char*. Therefore, the standard falls short of actually guaranteeing
interchangeability.
This suggests, for example, that this is valid code (and that g may be
called):

void f(void *p) {}
void g(void) {
((void(*)(char *)) f) ("Hello");
}

It doesn't actually work though, in at least gcc.
I'm curious - do you know the details of why it fails? I've known for
a long time that a lack of interchangeabiltiy is permitted, but it
would help to be able to cite the details of a real example of it,
particularly if its a compiler as widely available as gcc.
Sep 17 '08 #21

P: n/a
ja*********@verizon.net wrote:
Harald van Dk wrote:
...
>The standard says "The same representation and alignment requirements are
meant to imply interchangeability as arguments to functions, return values
from functions, and members of unions." in two footnotes.

Yes, that's precisely what I was thinking of. The problem is that it's
non-normative text. The normative text only requires same
representation and same alignment requirements. It's possible to
define function interface conventions that meet those two requirement,
while not allowing void* and char* to be interchangeable. For
instance, passing void* return values using a different register than
char*. Therefore, the standard falls short of actually guaranteeing
interchangeability.
The standard would still fall short
of actually guaranteeing interchangeability,
even if it had been in a normative part of the text
instead of in a footnote.

If it had been in the normative part of the standard,
instead of in a footnote,
the question would then be:
why does it say
"are meant to imply"
instead of
"imply"?

--
pete
Sep 17 '08 #22

P: n/a
pete <pf*****@mindspring.comwrites:
ja*********@verizon.net wrote:
>Harald van Dk wrote:
...
>>The standard says "The same representation and alignment requirements are
meant to imply interchangeability as arguments to functions, return values
from functions, and members of unions." in two footnotes.

Yes, that's precisely what I was thinking of. The problem is that it's
non-normative text. The normative text only requires same
representation and same alignment requirements. It's possible to
define function interface conventions that meet those two requirement,
while not allowing void* and char* to be interchangeable. For
instance, passing void* return values using a different register than
char*. Therefore, the standard falls short of actually guaranteeing
interchangeability.

The standard would still fall short
of actually guaranteeing interchangeability,
even if it had been in a normative part of the text
instead of in a footnote.

If it had been in the normative part of the standard,
instead of in a footnote,
the question would then be:
why does it say
"are meant to imply"
instead of
"imply"?
Obviously the wording would have to be changed in addition to just
moving it from the footnote. And dropping "are meant to" wouldn't
really help; the fact is that the representation and alignment
requirements *don't* imply interchangeability. There would have to
be an explicit requirements that the types *are* interchangeable.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 18 '08 #23

P: n/a
On Sep 16, 2:48 pm, Keith Thompson <ks...@mib.orgwrote:
"junky_fel...@yahoo.co.in" <junky_fel...@yahoo.co.inwrites:

[...]
And if that is correct, should we ever use void ** ?

void* can be used as a generic pointer type. What that means is that
a value of any pointer type (other than a pointer-to-function type)
can be converted to void* and back again without loss of information.

You might think that void** is therefore a generic pointer-to-pointer
type, but it isn't; in fact, there is no generic pointer-to-pointer
type.

You can convert an int*, or an int**, or an int***, or ... to void*
without loss of information -- except that you lose the type
information, which you have to carefully keep track of yourself.

--
How would you track the type information in this case?

Sep 18 '08 #24

P: n/a
Keith Thompson <ks...@mib.orgwrote:
... the fact is that the representation and alignment
requirements *don't* imply interchangeability. *There
would have to be an explicit requirements that the
types *are* interchangeable.
I'd prefer to see unprototyped functions finally removed
from C. Then I'd be happy with a statement that functions
in the standard library that are variadic, or use va_list,
use va_arg.

Although, I'd also prefer if va_arg could accept struct
pointers that are convertable to a common initial sequence,
but obviously that would imply a greater restriction to
the language (though I've never seen an implementation
where it might be an imposition.)

--
Peter
Sep 18 '08 #25

P: n/a
On Wed, 17 Sep 2008 14:33:26 -0700, jameskuyper wrote:
Harald van Dijk wrote:
...
>This suggests, for example, that this is valid code (and that g may be
called):

void f(void *p) {}
void g(void) {
((void(*)(char *)) f) ("Hello");
}

It doesn't actually work though, in at least gcc.

I'm curious - do you know the details of why it fails?
test.c: In function ‘g’:
test.c:3: warning: function called through a non-compatible type
test.c:3: note: if this code is reached, the program will abort

When gcc detects that a function is called through an incompatible
function pointer, and the function definition is available, it rejects the
call to prevent internal compiler errors when trying if inlining and such
makes sense. At least, that's how I remember it, but my memory may be off.
Sep 18 '08 #26

P: n/a
Chad wrote:
On Sep 16, 2:48 pm, Keith Thompson <ks...@mib.orgwrote:
>"junky_fel...@yahoo.co.in" <junky_fel...@yahoo.co.inwrites:

[...]
>>And if that is correct, should we ever use void ** ?
void* can be used as a generic pointer type. What that means is that
a value of any pointer type (other than a pointer-to-function type)
can be converted to void* and back again without loss of information.

You might think that void** is therefore a generic pointer-to-pointer
type, but it isn't; in fact, there is no generic pointer-to-pointer
type.

You can convert an int*, or an int**, or an int***, or ... to void*
without loss of information -- except that you lose the type
information, which you have to carefully keep track of yourself.

--

How would you track the type information in this case?
Thats pretty much up to you. There's no way to do it in absolute
generality, but if you have a small list of possibilities that are
relevant to the question, then the following is one example of how to do it:

#include <stdlib.h>
enum typecode { INTP /* many other codes */ };

struct multipointer {
enum typecode pointed_at;
void *pointer;
};

struct multipointer *multipointer_from_intpp(int **ipp)
{
struct multipointer *p = malloc(sizeof *p);
if(p)
{
p->pointed_at = INTP;
p->pointer = ipp;
}
return p;
}

void use_multipointer(struct multipointer *p)
{
if(p==NULL)
return;
switch(p->pointed_at)
{
case INTP:
{
int **ipp = (int **)p->pointer;

// code which works with ipp, such as
if(ipp && ipp[0])
**ipp = 0;
}
break;
// many other cases, including a default:
}
}
Sep 18 '08 #27

P: n/a
James Kuyper <ja*********@verizon.netwrites:
Keith Thompson wrote:
James Kuyper <ja*********@verizon.netwrites:
[...]
Any pointer to an object type can be converted to void* and
back. However, that does not mean that void* is compatible with all of
those other pointer type; it's only guaranteed to be compatible with
pointers to character types.
[...]

I understand what you mean, but "compatible" isn't the word for it.
The standard has a very specific definition for "compatible types"; by
that definition, void* and char* are not compatible.

C99 6.7.5.1p2:

For two pointer types to be compatible, both shall be identically
qualified and both shall be pointers to compatible types.

Since void and char are not compatible, void* and char* are not
compatible.

You're right: the standard requires them to have the same alignment
requirements and same representation, but they are not compatible
according to C's definition of the term. This is another of those cases
where the standard falls short of actually saying something that I think
it was actually intended to say. As a practical matter, they work just
as if they were compatible, on most implementations.
This reading is overly broad. The statement about having the
same representation and alignment requirements applies /only/
to value of these types, not to types derived from these types.
There isn't any reason to conclude that the standard requires
a (void**) and a (char**) to have the same representation,
or be interchangeable in any other way that compatible types
must be. The same statement holds for function types with
(void *) and (char *) in them.
Oct 9 '08 #28

P: n/a
ja*********@verizon.net writes:
Harald van D=A9=A6k wrote:
On Wed, 17 Sep 2008 17:37:51 +0000, James Kuyper wrote:
...
You're right: the standard requires them to have the same alignment
requirements and same representation, but they are not compatible
according to C's definition of the term. This is another of those cases
where the standard falls short of actually saying something that I thin=
k
it was actually intended to say. As a practical matter, they work just
as if they were compatible, on most implementations.
My compiler reports an error when I try

void f(char *p);
void f(void *p) {}

My compiler doesn't report an error when I try

void f(void *p);
void f(void *p) {}

or when I try

void f(int (*p)[]);
void f(int (*p)[30]) {}

I have trouble believing the intent was to allow the first, or that you
believe that was intended. If char * and void * were compatible, it would
be allowed, because compatible means something different from how you are
using it.

What I meant is a little more complicated than what I said. You can
work around the fact that those functions are incompatible by using
some type punning. The behavior of code that performs such type
punning is undefined, but I believe that it was the intent of the
committee that such type punning would work.
Again, this reading is overly broad, as explained in more detail in my
other responses. The standard does not require, nor does it intend to
require, that values of type (void (*)(char*)) be interchangeable with
values of type (void (*)(void*)). We can pass a (char*) value to
a function that expects a (void*), and it should work; but that
expectation does not extend to derived function types.

Oct 9 '08 #29

This discussion thread is closed

Replies have been disabled for this discussion.