something to do with void *

T

Tim Rentsch

Robert Gamble 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.

Whether a pointer value designates an object doesn't have to do with
the type or lvalue-ness of the expression that produced that value.
If you're willing to overlook the value of 'ptr' being indeterminate,
then it might very well have a value that designates an object. For
example:

int main(void)
{
struct foo;
struct foo *ptr /* = &abc */;
*ptr;
struct foo {
int x;
} abc;
return 0;
}

If the indeterminate value happens to coincide with the
not-allowed-because-of-forward-reference-problems "initialization"
inside the comment, then 'ptr' would designate an object (and
incidentally one of of appropriate type).

The appropriate section to cite here is 6.3.2.1 p2

"... If the lvalue has an incomplete type and does not have
array type, the behavior is undefined."
 
T

Tim Rentsch

CBFalconer said:
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?

Just because you aren't interested in the discussion doesn't
mean that other people aren't. The discussion is on topic;
arguably comp.std.c is a better place for it but it's
certainly on topic for one or the other and perhaps both.
As long as a discussion is on topic, then just delete
messages that strike you as inane, like the rest of do.

Furthermore, this discussion has value. There is value in
pointing out a weakness in what or whether the standard
allows or doesn't allow, and certainly there has been some
of that here. There is also a practical side. I for one
think C would benefit if treatment of void "values" were
more uniform with the rest of the language. For example,
'void' functions in C++ are allowed to 'return' void
expressions, to simplify certains kinds of automatic code
generation; I believe C would also benefit from such a
rule. This discussion of various void expressions shows
that cleaning up and making more consistent how void
expressions are handled is something that should at least be
considered.
 
S

S.Tobias

Netocrat said:
Chris said:
Netocrat wrote:
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,

I believe some confusion comes from misunderstanding what it means
to "evaluate an lvalue". It simply means "to establish location
of an object", it doesn't mean to read a value contained in an object.
A value is read when an lvalue-to-value conversion takes place.

The same subexpression may be interpreted as an lvalue, or as a value
depending on its position in an expression.
x = x;
Both expressions `x' are evaluated: the lhs is evaluated as an lvalue,
the rhs is evaluated as an lvalue and then one more step is performed:
lvalue-to-value conversion and the result is a value. (So both
expressions are "evaluated", but it has a slightly different meaning
in each case.)

In the case of a void expression, it is evaluated in a similar way
as an lvalue is, but since by definition it is not an lvalue no lvalue-
-to-value conversion is taken in any context, so there's no need
for the void type to contain any values (and indeed it hasn't any).
There are no side effects to dereferencing a void pointer.

By itself there aren't, of course, but there may be some while
calculating that pointer.
Its use as a value is forbidden because it isn't a value.

I find the quoted fragment especially contrived. It says: "You shall
not use something that doesn't exist anyway". What I think it means
to say is that an expression of type void shall not be used in a context
that requires a value. I think using void value in most cases would be
UB by omission (is it a CV anywhere?); maybe that particular fragment
(about use) is redundant, but I haven't looked enough, so I don't know
for sure.
 
S

S.Tobias

Tim Rentsch said:
For example,
'void' functions in C++ are allowed to 'return' void
expressions, to simplify certains kinds of automatic code
generation;

[OT] I think you're wrong, both in C and in C++ `return' works the same.
I miss this feature, too.
 
J

Joe Wright

Netocrat said:
Robert said:
Chris Dollin wrote:

[ Lots of snippage. I hope I kept the attribution right. ]
If you think the Standard is nonsense then you have no ground to argue
what is or is not Standard complient.


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.

You are going to have to elaborate on this.

The type 'void' is imaginary. It cannot be 'completed'. There are no
values and no objects of type void.

C89 gave us (void*) to represent the address of any object not a function.

The concept of void* allows implicit conversions of pointers among
object types. I could write much more about why void* is a 'good thing'.

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


The meaning your posts attribute to various concepts in C is usually
common-sense and I generally agree with what you write (even though it
seems to me that at times you ignore the actual wording of the standard -
but those are usually times when the standard is unspecific or conflicted
such as over whether a function returns an object or a value).
Thank you. You have 'read' me pretty well. I am not overly impressed by
some of the wording of the C99 Standard. I keep the Old Testament (KR1)
and New Testament (KR2) immediately next to my keyboard. These are
language references I find of inestimable value. I also have N869 as a
text file. I only use it to validate and perhaps illuminate for me some
of the claims about C99 posited here.

For the record, I use ..

'gcc -W -Wall -ansi -pedantic -s -O2 %1.c -o %1.exe -lm'

... to compile most of my programs. gcc is at 3.1 here.
The type void * is really a pointer to "anything" and would have been
better defined with a new type rather than as a pointer to the specific
type void. Void represents "nothing" rather than "anything". Someone
else has said something similar in this thread I think.
Yeah, ok. So what?
So I think that perhaps what you meant is that dereferencing an "anything"
pointer is nonsensical (what is an "anything"??), which I agree with.
Have it your way. All we have is void*.
Dereferencing a pointer to a void type is not nonsensical or undefined as
you say it is though - it yields a void expression which is well defined
and also occurs in other contexts.
I know exactly one context where void is meaningful, to define a
function as a procedure which has side effects but returns no value. Do
you know another C context for void?
I can't see any utility in being able to dereferencing an "anything"
pointer into a void expression though. I've never coded it other than
to test whether the compiler would accept it. So to me whether or not it
should be legal is hypothetical.
Again, we have only void* and no void object.
void *obj = malloc(19);
We have obj pointing to an object of void type. We have *obj an lvalue.
The type of *obj is void. There is no question of finding "utility" for
this circumstance and its legality is not hypothetical, it is nonsense.
Consider ..
*obj = 0;
... Search for Sanity.
 
N

Netocrat

I am not overly impressed by
some of the wording of the C99 Standard. I keep the Old Testament (KR1)
and New Testament (KR2) immediately next to my keyboard. These are
language references I find of inestimable value.

I learnt from KR2 (after the basics). It deserves its reputation.
Yeah, ok. So what?

It seems inconsistent to me. A pointer to anything has been defined to be
a pointer to nothing. I think that it would be better defined as
pointing to an unknown type rather than a void type, with use of that
unknown type invalid except as part of a pointer. The void type has its
use(s), but I don't think that this should have been one of them.
I know exactly one context where void is meaningful, to define a
function as a procedure which has side effects but returns no value. Do
you know another C context for void?

Off the top of my head I can't point to another context for void.
Perhaps I should have used singular.
Again, we have only void* and no void object.

Yup, that's why I think that "unknown" is a more appropriate type for
this pointer. Pointing to an object of unknown type makes more sense than
pointing to an object of a type not allowed to be an object.
void *obj = malloc(19);
We have obj pointing to an object of void type. We have *obj an lvalue.

I don't believe it's intended to be specified as an lvalue by the
standard, although as Stan Tobias argues it may unintendedly be.
The type of *obj is void. There is no question of finding "utility" for
this circumstance and its legality is not hypothetical, it is nonsense.
Consider ..
*obj = 0;

That is obviously nonsensical. Thankfully it's prohibited.
 
T

Tim Rentsch

S.Tobias said:
Tim Rentsch said:
For example,
'void' functions in C++ are allowed to 'return' void
expressions, to simplify certains kinds of automatic code
generation;

[OT] I think you're wrong, both in C and in C++ `return' works the same.
I miss this feature, too.

I double checked via a Google search, and turned up these
pages (among others):

http://www.ittips.com/computersindex_v2-103-1.htm
http://www.edg.com/cpp_ftrs.html

So it seems like the latest version of the C++ standard
does support 'return' with void expressions for 'void'
functions.
 
T

Tim Rentsch

Netocrat said:
Chris Dollin wrote:
[snip-snip-snip]
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.

It's a little nicer, and just as consistent, to think of
void as having a single value that, because it's always the
same, takes zero bits to store, and is completely optimized
in both space and run-time by all C compilers. It's because
the value takes zero bits to represent that it is called
"nonexistent", not because there is no value. The zero-bit
void value is what's accessed (using no instructions) by
expressions like '*vp'. Remember, an object is "a region of
data storage in the execution environment, the contents of
which can represent values"; there's nothing that says the
region needs to be non-empty. There could be a problem with
void arrays, since the usual calculation for number of
elements ('sizeof x / sizeof *x') doesn't work if 'sizeof x'
is zero, but that minor difficulty can easily be gotten
around.

Somewhat tongue-in-cheek, but only somewhat.
 
S

S.Tobias

Netocrat said:
Off the top of my head I can't point to another context for void.
Perhaps I should have used singular.

Everywhere, where value is not expected:

//function call, in expression statement; most common
vf();

//operand subexpressions
(void_expr1, void_expr2);
cond ? void_expr1 : void_expr2;

//common idioms
(void) variable; //suppress warnings about unused variables or arguments
(void) int_fn(); //returned value is discarded

Yup, that's why I think that "unknown" is a more appropriate type for
this pointer. Pointing to an object of unknown type makes more sense than
pointing to an object of a type not allowed to be an object.

I think "unknown" is the word for type `void'. If C had
an `unknown' type, would it be in any way different than `void'?

Note also that not everything need be quite unknown - we have
`const void' and `volatile void'.
I don't believe it's intended to be specified as an lvalue by the
standard, although as Stan Tobias argues it may unintendedly be.

I don't remember doing that. `*obj' is type void, and therefore
is *not* an lvalue.
That is obviously nonsensical. Thankfully it's prohibited.

It's prohibited, but not because dereferencing (void*) is.
It is because lhs must be a modifiable lvalue.

Dereferencing pointers to void may seem nonsense, but OTOH there's
no reason to ban it, since other void expressions are allowed.
 
N

Netocrat

Netocrat <[email protected]> wrote:

I think "unknown" is the word for type `void'. If C had an `unknown'
type, would it be in any way different than `void'?

Its definition would limit it solely to use as a pointed-to type for a
generic pointer to any object. Dereferencing such a pointer would not
be possible (the pointed-to type is unknown).

I don't remember doing that.

Must be a case of identity theft then. Someone recently started an entire
thread devoted to the issue on comp.std.c in your name.

Dereferencing pointers to void may seem nonsense, but OTOH there's no
reason to ban it, since other void expressions are allowed.

Which for me is good enough reason to prefer a new type "unknown" rather
than void for use in a generic object pointer.
 
N

Netocrat

"Netocrat" <[email protected]> writes: ....
It's a little nicer, and just as consistent, to think of
void as having a single value that, because it's always the
same, takes zero bits to store, and is completely optimized
in both space and run-time by all C compilers.
<snip>

OK void could be defined as a type with a single unique empty value as
you and Chris describe, but it seems contrary to the purpose of void,
which is to represent an expression that does something (has side effects)
but doesn't result in a direct value. To me the value of void as a value
is valueless.
There could be a problem with
void arrays, since the usual calculation for number of
elements ('sizeof x / sizeof *x') doesn't work if 'sizeof x'
is zero, but that minor difficulty can easily be gotten
around.

Somewhat tongue-in-cheek, but only somewhat.

I don't even want to contemplate Chuck's reaction to a discussion of void
arrays. ;)
 
S

S.Tobias

Tim Rentsch said:
S.Tobias said:
Tim Rentsch said:
For example,
'void' functions in C++ are allowed to 'return' void
expressions, to simplify certains kinds of automatic code
generation;

[OT] I think you're wrong, both in C and in C++ `return' works the same.
I miss this feature, too.

I double checked via a Google search, and turned up these
pages (among others):

http://www.ittips.com/computersindex_v2-103-1.htm
http://www.edg.com/cpp_ftrs.html

So it seems like the latest version of the C++ standard
does support 'return' with void expressions for 'void'
functions.

Thanks, I wasn't aware of that, you're right. I've looked into
the C++03 Std now, and it agrees with you.
 
T

Tim Rentsch

Netocrat said:
<snip>

OK void could be defined as a type with a single unique empty value as
you and Chris describe, but it seems contrary to the purpose of void,
which is to represent an expression that does something (has side effects)
but doesn't result in a direct value. To me the value of void as a value
is valueless.

Rather than thinking of void as a type that means "no value"
you might think of void as a type whose sole value is "empty".
The empty set is still a set, even though it is empty.

The value of a void expression, because it is "worthless", is
discarded.

Again, somewhat tongue in cheek. However, I think this view
is equally consistent, and it could simplify treatment of void
expresssions.
 
S

S.Tobias

Netocrat said:
Its definition would limit it solely to use as a pointed-to type for a
generic pointer to any object. Dereferencing such a pointer would not
be possible (the pointed-to type is unknown).

Equivalent solution would be to disallow dereferencing `void*' (while
still allowing void expressions).

Another way to look at `void' is to call it "empty", and apply
it to whatever fits that emptiness (void expressions, which represent
"Nothing", and pointers to "Unknown" which can't point to any concrete
value).

Perhaps the name "void" is is a little bit "overloaded" in that in `void*'
it means a slightly different thing than in plain `void'.
Personally, I'm quite happy with the simple way it is now and I wouldn't
welcome any changes there.

Must be a case of identity theft then. Someone recently started an entire
thread devoted to the issue on comp.std.c in your name.

:)
Oh, you mean that one... But I strongly believe that void expressions
aren't lvalues and should never be, even if the Std says otherwise. ;-)
 
F

Free Bird

Netocrat said:
Chris said:
Netocrat said:
Chris Dollin wrote:
Netocrat wrote:
*snip*
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.

What if it is volatile?
 
N

Netocrat

Netocrat said:
Chris said:
Netocrat wrote:

Chris Dollin wrote:
Netocrat wrote:
*snip*
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.

What if it is volatile?

Still not a side effect. The pointer does not reference an object with a
value, so there is nothing that may have changed.
 
N

Netocrat

Perhaps the name "void" is is a little bit "overloaded" in that in
`void*' it means a slightly different thing than in plain `void'.

That's the issue exactly.
Personally, I'm quite happy with the simple way it is now and I wouldn't
welcome any changes there.

Oh I'm not seriously advocating a new type - it all works fine in
practice. I'm just pointing out that as you seem to agree there's a
little conceptual inconsistency in the model. It would be cleared up
by not using void* for an unknown pointer.
 

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