something to do with void *

K

Keith Thompson

Keith Thompson said:
Upthread, you mentioned that there have been several DRs confirming
that dereferencing a void* is legal. Do you have pointers to these?

Elsethread, you mentioned DR 106
(<http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_106.html>), which
seems to establish that *ptr is valid when ptr is of type void*. It
refers to the C90 standard, but I don't think there was any deliberate
change in this area in C99.

I still think it would be better if the standard said so explicitly.
 
C

Chris Dollin

Robert said:
The result of dereferencing a void pointer is an expression of type
void, good so far.

This so blatantly false I don't know what to make of it; there's likely
some terminological mismatch.

The result of dereferencing a pointer-to-T is a value of type T, not
an expression of any kind.

The *expression* `*p`, where `p` is of type pointer-to-T, is an
expression of type `T`. If this expression is legal and defined, #
its value is an instance of type T, one of T's values.
 
C

Chris Dollin

Richard said:
Chris Dollin said:
Robert said:
Chris Dollin wrote:
[1] No, I don't subscribe to the nonsense that `void` is an empty
[type.
6.2.5p19:
"The void type comprises an empty set of values; it is an incomplete
type that cannot be completed."

Yes, I know. That's why I said that I didn't subscribe to that
nonsense; because I don't. The view that `void` is an empty type
leads to unfortunate conclusions about the existance of functions
returning void, which are trivially avoided by making void have
a unique instance.

I think you have that backwards. If void had a unique instance, void
functions would return that instance,
Exactly.

which could be used or assigned to something.

Indeed. I see no problem here.
Since void is empty and does _not_ have any values, a void
function returns nothing,

In fact, it can't return, because it can't exist, because it
has no range - if void is an empty type.
 
R

Richard Bos

Chris Dollin said:
Richard said:
Chris Dollin said:
Robert Gamble wrote:

Chris Dollin wrote:
[1] No, I don't subscribe to the nonsense that `void` is an empty
[type.
6.2.5p19:
"The void type comprises an empty set of values; it is an incomplete
type that cannot be completed."

Yes, I know. That's why I said that I didn't subscribe to that
nonsense; because I don't. The view that `void` is an empty type
leads to unfortunate conclusions about the existance of functions
returning void, which are trivially avoided by making void have
a unique instance.

I think you have that backwards. If void had a unique instance, void
functions would return that instance,
Exactly.

which could be used or assigned to something.

Indeed. I see no problem here.

You don't? So

void func(int a);
int b, c=0;

b=(int)func(c);

doesn't slightly surprise you?
In fact, it can't return, because it can't exist, because it
has no range - if void is an empty type.

I'm sorry, but that's just nonsense. Of course it can return! It just
doesn't return _a value_ to its caller - all it returns is the flow
control.

Richard
 
R

Richard Bos

Joe Wright said:
But void is an imaginary type that cannot be completed. Dereferencing
void* is not just Undefined Behavior, it is nonsense.

No, that's too strong, IYAM. Merely dereferencing a void * isn't
undefined behaviour. What causes undefined behaviour is doing anything
with the result.
The Standard clearly states that if p is a void *, then *p is an
expression with type void. What it does _not_ state is what value that
expression has - naturally, since it has none.

Richard
 
C

Chris Dollin

Robert said:
void is an incomplete type, a pointer to void is not. We are talking
about dereferencing a pointer to void.

Sorry; I was tangled. I meant that pointers to incomplete types cannot
be dereferenced, last time I looked.
the result would be the unique
value of the void type [1], which isn't an int either.

It yields an expression of type void. Not sure what you mean by unique
value of void type.

Evaluating an expression of type T returns a result which is an
instance of T -- eg, `1+2` is an expression of type `int` who's
result is the value `3`, an instance of `int`.

The unique value of type `void` is the single, unique value which
is of type `void`.

That makes no sense.

Sure it does. Singleton types - types with but a single value - are
perfectly straightforward. COuld you unpack your problem with the above
a bit?
[1] No, I don't subscribe to the nonsense that `void` is an empty
[type.

Oh, not one of those suckers who blindly subscribes to the Standard?

That's right.

Well there is little hope for you then.

Strange - my experience doesn't bear that out.
You talk about what is "legal
in standard C" and then admit that you don't accept the Standard itself

False. I don't accept that particular technicality in the Standard
as a consistent way of describing the behaviour of `void` and
`pointer-to-void`. I accept that it *is* the way the Standard
describes it.
making your entire argument completely pointless.

Premise false, conclusion does not follow.
If you think the Standard is nonsense

See above.
then you have no ground to argue what is or is not Standard complient.

Even if you were right to believe that I thought the /entire/ Standard
was nonsense, I don't see why you would think that I couldn't sensibly
talk about compliance with that Standard.
You are going to have to elaborate on this.

My elaboration was broken (I believe repairable, but still broken).
It did not take enough account of side-effects (which, pragmatically,
are the point of calling void functions in the first place) and
also contained an amusing off-by-one error. Witness:

If T is an empty type, then there are no functions of type X -> T
for any X. [Off-by-one: there is /one/ such function; it is
represented by the empty set [of arg-result pairs].]

Of course C functions don't map in such a trivial fashion to
mathematic ones, so the argument was handwavy anyway; I believe,
but without more analysis, that it can be cleanly reconstructed.
 
C

Chris Dollin

Richard said:
You don't? So

void func(int a);
int b, c=0;

b=(int)func(c);

doesn't slightly surprise you?

Given the premise - that `void` had a unique value - the only
surprise is that the writer didn't just initialise `b` to `0`
straightaway, rather than casting the result of `func`.
I'm sorry, but that's just nonsense. Of course it can return! It just
doesn't return _a value_ to its caller

See elsethread for my own retraction of my simplistic analysis,
but note that it's consistent to descibe the function as returning
a value - the empty tuple will do fine.
- all it returns is the flow control.

It's more POV than I had previously thunk.
 
N

Netocrat

This so blatantly false I don't know what to make of it; there's likely
some terminological mismatch.

The result of dereferencing a pointer-to-T is a value of type T, not
an expression of any kind.

Can you point out where in the standard it says that? I can't find it, so
I'm assuming that's what you think it should say.
The *expression* `*p`, where `p` is of type pointer-to-T, is an
expression of type `T`.
Agreed.

If this expression is legal and defined, # its
value is an instance of type T, one of T's values.

I can't see where the standard requires that the result is a value. The
quote top of post seems accurate to the wording of 6.5.3.2#4 which doesn't
use the word value to describe the result. Given that a void type can't
have a value, the use of the term "expression" seems appropriate.

As I've argued elsewhere I think that what you're describing should be
mandated by the standard, but I don't think it actually is.
 
N

Netocrat

<snip discussion on dereferencing a void pointer, argued by
Robert and accepted with qualifications by Keith as being valid>
Also, what do you think about the following?

int main(void)
{
struct foo;
struct foo *ptr;
*ptr;
struct foo {
int x;
};
return 0;
}

Since struct foo is an incomplete type, I would think that the same
logic would lead us to conclude that *ptr is legal. (gcc 4.0.0 says
"error: dereferencing pointer to incomplete type".)

See Stan Tobias' post in the recent thread gcc: pointer to array:
http://groups-beta.google.com/group/comp.lang.c/msg/f91eac210c8d77b7?hl=en&

In short, *ptr is undefined behaviour by 6.3.2.1#2. Dereferencing a void
pointer does not yield an lvalue so the same paragraph does not apply.
 
R

Robert Gamble

Keith said:
Robert Gamble said:
Keith Thompson wrote:
[snip]
That doesn't prove anything. gcc, even in conforming mode, produces
warnings rather than error messages for things that are constraint
violations as far as the standard is concerned.

The standard requires a diagnostic for any syntax error or constraint
violation. Either a warning (which allows the compilation to succeed)
or an error message (which does) qualifies as a diagnostic. And, of
course, it's allowed to produce any additional diagnostics it likes.

We can't tell from the above output whether the warning is a required
diagnostic or not.

The assertion made by Emmanuel was that all compilers that he was aware
of forbade the dereferencing of void pointers. He didn't mention any
of these compilers but gcc was obviously one of them. I produced a
program that was successfully compiled on several versions of gcc inn
strictly-conforming mode, none of why "forbade" my doing so. When
pressed, Emmanuel could not back up his claims (see his response).
Additionally, the other compilers I tried in strictly-conforming mode
produced no messages at all.

Ok, as a refutation of what Emmanuel wrote, it's fine.

[snip]
Well, lets break it down then:

'The operand of the unary * operator shall have pointer type.'

I think we agree that this is clear.
Sure.

'The unary * operator denotes indirection. If the operand points to a
function, the result is a function designator; if it points to an
object, the result is an lvalue designating the object.'

This is the part that makes me suspicious. It tells us what the
result is in two out of three cases (points to a function, points to
an object, but not points to an incomplete type). When something in
the standard covers some cases but is silent on others, I tend to
think (correctly or not) that the authors just didn't think about it.
The operand does not point to a function and it does not point to an
object (if you disagree with this, see the discussion on comp.std.c but
bear with me) so this part does not apply to void pointers.

I'll agree that a void* pointer does not point to an object in the
context of this section.
'If the operand has type "pointer to type", the result has type "type"'

For a "pointer to void" the result has type "void". I think this is as
clear as you can expect.

I think I agree -- but on the other hand, one could argue that a
result is a value, and since there are no values of type void, we have
a contradiction.

There is no requirement that a result have a value, it certainly isn't
a value in and of itself.
I don't think there is an obviously correct interpretation of this.
I tend to think that allowing dereferencing a void pointer as long as
you don't try to use the value is the least ugly interpretation,
especially given the precedent of calling a void function. On the
other hand, if dereferencing a void pointer were illegal, I don't
think it would break any code that doesn't deserve to be broken.

Upthread, you mentioned that there have been several DRs confirming
that dereferencing a void* is legal. Do you have pointers to these?

http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_012.html
http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_106.html
I thought there was another but I may be wrong.
Also, what do you think about the following?

int main(void)
{
struct foo;
struct foo *ptr;
*ptr;
struct foo {
int x;
};
return 0;
}

Since struct foo is an incomplete type, I would think that the same
logic would lead us to conclude that *ptr is legal. (gcc 4.0.0 says
"error: dereferencing pointer to incomplete type".)

First off, *ptr is undefined behavior (even after the type it points to
is completed) because the value of ptr is indeterminate, but let's but
that aside for now.

At the point where ptr is dereferenced, it is a pointer to an
incomplete type. The result is therefore an incomplete type (If the
operand has type "pointer to type", the result has type "type").

The first sentence of 6.3.2.1p1 states:
'An lvalue is an expression with an object type or an incomplete type
other than void; if an lvalue does not designate an object when it is
evaluated, the behavior is undefined.'

The first part of this sentence tells us that the result of *ptr is an
lvalue, the second part tells us that since it does not designate an
object the behavior is undefined allowing gcc to refuse to compile the
program.

Robert Gamble
 
C

Chris Dollin

Netocrat said:
Can you point out where in the standard it says that? I can't find it, so
I'm assuming that's what you think it should say.

It's what I thought the meaning of what is written is.

[References herewith to the N869 draft, since I don't have a
copy of the final Standard to hand. I hope nothing essential
changed since ...]
I can't see where the standard requires that the result is a value. The
quote top of post seems accurate to the wording of 6.5.3.2#4 which doesn't
use the word value to describe the result.

Hmm. That wording appears to leave a loophole, and my wording appears
to have been unnecessarily sloppy. I'd been thinking of the `*p`
expression appearing where a value is required, but of course it
can appear as the target of an assignment [or the operand of an &],
and so `*p` must [ignoring the case of function pointers] be an
lvalue, which when evaluated will deliver some value [if that is
legal].

[Assuming that the target of an assignment must be a modifiable
lvalue, it cannot be of type void by 6.3.2.1, so `*p` where
`p` has type pointer-to-void only makes sense where the value
is required or the expression contains `&*p`, so my sloppiness
above doesn't seem break the argument.]

So, in the case of `void *p`, can `p` "point to an object"?
Given that a void type can't
have a value, the use of the term "expression" seems appropriate.

`Expression` *cannot* be right; expressions are things that the grammar
describes and the compiler handles, but they don't have to exist at
run-time, when evaluation takes place.

["Don't have to" is weasel-wording to avoid the possibility that
the program is /about/ expressions, eg a compiler ...]
As I've argued elsewhere I think that what you're describing should be
mandated by the standard, but I don't think it actually is.

It does appear that the devil is in the details.
 
N

Netocrat

Netocrat said:
Can you point out where in the standard it says that? I can't find it,
so I'm assuming that's what you think it should say.

It's what I thought the meaning of what is written is.

[References herewith to the N869 draft, since I don't have a
copy of the final Standard to hand. I hope nothing essential changed
since ...]
I can't see where the standard requires that the result is a value.
The quote top of post seems accurate to the wording of 6.5.3.2#4 which
doesn't use the word value to describe the result.

Hmm. That wording appears to leave a loophole, and my wording appears to
have been unnecessarily sloppy. I'd been thinking of the `*p` expression
appearing where a value is required, but of course it can appear as the
target of an assignment [or the operand of an &], and so `*p` must
[ignoring the case of function pointers] be an lvalue, which when
evaluated will deliver some value [if that is legal].

[Assuming that the target of an assignment must be a modifiable
lvalue, it cannot be of type void by 6.3.2.1, so `*p` where `p` has
type pointer-to-void only makes sense where the value is required or
the expression contains `&*p`, so my sloppiness above doesn't seem
break the argument.]

Is a value required when the entire expression is *p;?

&*p does not dereference under C99.

There doesn't seem to be any reason to dereference a void pointer does
there?
So, in the case of `void *p`, can `p` "point to an object"?

Yes, in some contexts... but probably not in this context - at least
not as intended by the standard.

See the thread:

http://groups-beta.google.com/group...b70a6017215/a6b7078dafa8d9ec#a6b7078dafa8d9ec

In particular Robert Gamble's fourth post; Douglas Gwyn's 2nd post and
my reply.
`Expression` *cannot* be right; expressions are things that the grammar
describes and the compiler handles, but they don't have to exist at
run-time, when evaluation takes place.

Is it evaluated?

<snip rest>
 
C

Chris Dollin

Netocrat said:
The result of dereferencing a pointer-to-T is a value of type T, not
an expression of any kind.

Can you point out where in the standard it says that? I can't find it,
so I'm assuming that's what you think it should say.

It's what I thought the meaning of what is written is.

[References herewith to the N869 draft, since I don't have a
copy of the final Standard to hand. I hope nothing essential changed
since ...]
The *expression* `*p`, where `p` is of type pointer-to-T, is an
expression of type `T`.

Agreed.

If this expression is legal and defined, # its value is an instance of
type T, one of T's values.

I can't see where the standard requires that the result is a value.
The quote top of post seems accurate to the wording of 6.5.3.2#4 which
doesn't use the word value to describe the result.

Hmm. That wording appears to leave a loophole, and my wording appears to
have been unnecessarily sloppy. I'd been thinking of the `*p` expression
appearing where a value is required, but of course it can appear as the
target of an assignment [or the operand of an &], and so `*p` must
[ignoring the case of function pointers] be an lvalue, which when
evaluated will deliver some value [if that is legal].

[Assuming that the target of an assignment must be a modifiable
lvalue, it cannot be of type void by 6.3.2.1, so `*p` where `p` has
type pointer-to-void only makes sense where the value is required or
the expression contains `&*p`, so my sloppiness above doesn't seem
break the argument.]

Is a value required when the entire expression is *p;?

Certainly, absent some remark in the Standard that says things that
would normally be executed are not. You can't just arbitrarily decide
not to evaluate an expression. Optimisers are of course free to
eliminate code that doesn't have /visible/ effects, and even to
assume that the program doesn't exhibit UB, but that's different.
Isn't it?
&*p does not dereference under C99.

There doesn't seem to be any reason to dereference a void pointer does
there?

There isn't any reason to write the expression `(1+0)` in place
of the expression `(1)`, either, but that doesn't mean that it
shouldn't be interpreted in the usual way.
Yes, in some contexts... but probably not in this context - at least
not as intended by the standard.

See the thread:

http://groups-beta.google.com/group...b70a6017215/a6b7078dafa8d9ec#a6b7078dafa8d9ec

In particular Robert Gamble's fourth post; Douglas Gwyn's 2nd post and
my reply.


Is it evaluated?

Is there something in the Standard that prevents it?
 
N

Netocrat

Robert said:
First off, *ptr is undefined behavior (even after the type it points to
is completed) because the value of ptr is indeterminate, but let's but
that aside for now.

At the point where ptr is dereferenced, it is a pointer to an
incomplete type. The result is therefore an incomplete type (If the
operand has type "pointer to type", the result has type "type").

The first sentence of 6.3.2.1p1 states:
'An lvalue is an expression with an object type or an incomplete type
other than void; if an lvalue does not designate an object when it is
evaluated, the behavior is undefined.'

The first part of this sentence tells us that the result of *ptr is an
lvalue, the second part tells us that since it does not designate an
object the behavior is undefined allowing gcc to refuse to compile the
program.

An incomplete type can designate an object.

int main(void)
{
int (*bar)[];
(*bar)[1];
return 0;
}

Undefined behaviour because bar is uninitialised, but *bar _could_
designate an object - gcc doesn't complain about it. It's the second
paragraph of 6.3.2.1, not the first, that describes Keith's example as
undefined behaviour.
 
N

Netocrat

Chris said:
Certainly, absent some remark in the Standard that says things that
would normally be executed are not. You can't just arbitrarily decide
not to evaluate an expression.

Is there something in the Standard that prevents it?

6.3.2.2#1: "The (nonexistent) value of a void expression (an expression
that has type void) shall not be used in any way [...] (A void
expression is evaluated for its side effects.)"
 
C

Chris Dollin

Netocrat said:
Chris said:
Certainly, absent some remark in the Standard that says things that
would normally be executed are not. You can't just arbitrarily decide
not to evaluate an expression.

Is there something in the Standard that prevents it?

6.3.2.2#1: "The (nonexistent) value of a void expression (an expression
that has type void) shall not be used in any way [...] (A void
expression is evaluated for its side effects.)"

So it is evaluated, and the (nonexistant) value sort-of exists;
it exists at least enough for its use to be forbidden!

It looks like I've fallen into a can of worms that I didn't appreciate;
it's been too long since I last read the Standard.

However, I count it as evidence that the `void has no values` view
is tricky; certainly trickier than `void has one value`, which I
think just works without special additional machinery. But of course
I could be wrong.
 
N

Netocrat

Chris said:
Netocrat said:
Chris said:
Netocrat wrote:
On Tue, 02 Aug 2005 09:18:08 +0100, Chris Dollin wrote:

Is a value required when the entire expression is *p;?

Certainly, absent some remark in the Standard that says things that
would normally be executed are not. You can't just arbitrarily decide
not to evaluate an expression.
Given that a void type can't
have a value, the use of the term "expression" seems appropriate.

`Expression` *cannot* be right; expressions are things that the
grammar describes and the compiler handles, but they don't have to
exist at run-time, when evaluation takes place.

Is it evaluated?

Is there something in the Standard that prevents it?

6.3.2.2#1: "The (nonexistent) value of a void expression (an expression
that has type void) shall not be used in any way [...] (A void
expression is evaluated for its side effects.)"

So it is evaluated,

There are no side effects to dereferencing a void pointer.
and the (nonexistant) value sort-of exists;
it exists at least enough for its use to be forbidden!

Its use as a value is forbidden because it isn't a value.
It looks like I've fallen into a can of worms that I didn't appreciate;
it's been too long since I last read the Standard.

Areas like this are hard to interpret, probably because they're not of
much practical importance and not as much thought was put into crafting
them sensibly.
However, I count it as evidence that the `void has no values` view
is tricky; certainly trickier than `void has one value`, which I
think just works without special additional machinery. But of course
I could be wrong.

Hmmm. I don't see any reason for void to be/have a value. Some
expressions don't and shouldn't be forced to have values.
 
C

CBFalconer

Netocrat said:
.... snip ...

Hmmm. I don't see any reason for void to be/have a value. Some
expressions don't and shouldn't be forced to have values.

Something like 37 largely inane messages have flown by here
discussing this bit of metaphysics and code that nobody anywhere
near their right mind would write. How many *void*s can dance on a
single memory cell? Ridiculous. Is this going to die out or do I
need to PLONK the thread?
 
P

pete

Chris Dollin wrote:
The result of dereferencing a pointer-to-T is a value of type T,
not an expression of any kind.

The *expression* `*p`, where `p` is of type pointer-to-T, is an
expression of type `T`. If this expression is legal and defined, #
its value is an instance of type T, one of T's values.

There is no difference.
The result of dereferencing pointer p, is *p.
 
T

Tim Rentsch

Keith Thompson said:
Robert Gamble said:
Keith Thompson wrote: [snip]
C99 6.5.3.2p2 says

The operand of the unary * operator shall have pointer type.

6.5.3.2p4 says

The unary * operator denotes indirection. If the operand points to
a function, the result is a function designator; if it points to
an object, the result is an lvalue designating the object. If the
operand has type "pointer to type", the result has type "type". If
an invalid value has been assigned to the pointer, the behavior of
the unary * operator is undefined.

It seems ambiguous to me.

Well, lets break it down then: [snip]
'The unary * operator denotes indirection. If the operand points to a
function, the result is a function designator; if it points to an
object, the result is an lvalue designating the object.'

This is the part that makes me suspicious. It tells us what the
result is in two out of three cases (points to a function, points to
an object, but not points to an incomplete type). When something in
the standard covers some cases but is silent on others, I tend to
think (correctly or not) that the authors just didn't think about it.

Note the language. It doesn't say "If the type of the expression has
function type [or object type]"; it says "If the operand points to a
function [or to an object]". A pointer (other than a NULL pointer)
can only point to a function or to an object; there's no such thing
as "an incomplete object". So the third case you mention may not
apply here.

No conclusion, just making an observation.
 

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

Forum statistics

Threads
474,169
Messages
2,570,915
Members
47,456
Latest member
JavierWalp

Latest Threads

Top