471,067 Members | 1,559 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,067 software developers and data experts.

something to do with void *

hello, this is a piece of code ,which is giving an error.
#include<stdio.h>

int main()
{
int a =10;
void *p = &a;
printf("%d ", *p ); //error....why should it //be an error ?can't the
compiler make out because //of %d that the pointer is supposed to refer to
an integer ?? or is explicit type casting required ??
++p ; //agree that this is an error.
return 0;
}

plssss tell me about the first error.thanx.
ranjan.

Nov 15 '05 #1
56 2996
maadhuu wrote:
hello, this is a piece of code ,which is giving an error.
#include<stdio.h>

int main()
{
int a =10;
void *p = &a;
printf("%d ", *p ); //error....why should it //be an error ?can't the
compiler make out because //of %d that the pointer is supposed to refer to
an integer ?? or is explicit type casting required ??


*p is illegal because you are not permitted to dereference a void
pointer. That you clearly "intended" *p to be an int doesn't permit
the compiler to ignore the error.

If *someVoidPointer *were* legal, the result would be the unique
value of the void type [1], which isn't an int either.

[1] No, I don't subscribe to the nonsense that `void` is an empty type.

--
Chris "electric hedgehog" Dollin
predicting self-predictors' predictions is predictably unpredictable.
Nov 15 '05 #2
Chris Dollin wrote:
maadhuu wrote:
hello, this is a piece of code ,which is giving an error.
#include<stdio.h>

int main()
{
int a =10;
void *p = &a;
printf("%d ", *p ); //error....why should it //be an error ?can't the
compiler make out because //of %d that the pointer is supposed to refer to
an integer ?? or is explicit type casting required ??
*p is illegal because you are not permitted to dereference a void
pointer. That you clearly "intended" *p to be an int doesn't permit
the compiler to ignore the error.


In this case the printf statement is incorrect, but simply
dereferencing a valid void pointer is not illegal.
If *someVoidPointer *were* legal
Which it is...
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.
[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?

6.2.5p19:
"The void type comprises an empty set of values; it is an incomplete
type that cannot be completed."

Robert Gamble

Nov 15 '05 #3
maadhuu <ma************@yahoo.com> wrote:
int main()
{
int a =10;
void *p = &a;
printf("%d ", *p );
can't the compiler make out because of %d that the pointer is supposed
to refer to an integer?
No.
++p; //agree that this is an error.
The same principle applies; if the compiler knew what p pointed at,
then both this and *p would be acceptable.
or is explicit type casting required ??


Yes.

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 15 '05 #4
Robert Gamble wrote:
Chris Dollin wrote:
maadhuu wrote:
> hello, this is a piece of code ,which is giving an error.
> #include<stdio.h>
>
> int main()
> {
> int a =10;
> void *p = &a;
> printf("%d ", *p ); //error....why should it //be an error ?can't
> the
> compiler make out because //of %d that the pointer is supposed to refer
> to an integer ?? or is explicit type casting required ??
*p is illegal because you are not permitted to dereference a void
pointer. That you clearly "intended" *p to be an int doesn't permit
the compiler to ignore the error.


In this case the printf statement is incorrect, but simply
dereferencing a valid void pointer is not illegal.
If *someVoidPointer *were* legal


Which it is...


I beg to differ. It is not legal in standard C. Your very own quote
below says that `void` is an incomplete type, and incomplete types
cannot be dereferenced when I last 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`.
[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.
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.

--
Chris "electric hedgehog" Dollin
predicting self-predictors' predictions is predictably unpredictable.
Nov 15 '05 #5
Chris Dollin <ke**@hpl.hp.com> wrote:
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, which could be used or assigned to
something. Since void is empty and does _not_ have any values, a void
function returns nothing, not even a unique instance, and you can't
assign nothing to an object.

Richard
Nov 15 '05 #6
Chris Dollin wrote:
Robert Gamble wrote:
Chris Dollin wrote:
maadhuu wrote:

> hello, this is a piece of code ,which is giving an error.
> #include<stdio.h>
>
> int main()
> {
> int a =10;
> void *p = &a;
> printf("%d ", *p ); //error....why should it //be an error ?can't
> the
> compiler make out because //of %d that the pointer is supposed to refer
> to an integer ?? or is explicit type casting required ??

*p is illegal because you are not permitted to dereference a void
pointer. That you clearly "intended" *p to be an int doesn't permit
the compiler to ignore the error.
In this case the printf statement is incorrect, but simply
dereferencing a valid void pointer is not illegal.
If *someVoidPointer *were* legal


Which it is...


I beg to differ. It is not legal in standard C. Your very own quote
below says that `void` is an incomplete type, and incomplete types
cannot be dereferenced when I last looked.


void is an incomplete type, a pointer to void is not. We are talking
about dereferencing a pointer to void.
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.
[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. You talk about what is "legal
in standard C" and then admit that you don't accept the Standard itself
making your entire argument completely pointless.
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.


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.

Robert Gamble

Nov 15 '05 #7
printf is not part of the C language, its part of the library. The
compiler has no idea what %d in your string is supposed to mean. It
simply gets passed and interpretted at runtime. The C compiler doesn't
"look into" strings, nor what they are getting passed to.

Remember, printf could be overridden by your own code. You could
redefine printf to do something completely different and link it into
your code, which does not do anything at all with %d. printf is simply
a library function, not a part of the language itself.

Jon
----
Learn to program using Linux assembly language
http://www.cafeshops.com/bartlettpublish.8640017
Nov 15 '05 #8
Jonathan Bartlett <jo*****@eskimo.com> wrote:

[ Do not post without content. Google are bad enough netizens to do so,
but this does not mean you should emulate them. ]
printf is not part of the C language, its part of the library.
That distinction is meaningless. printf() is part of a correct C
implementation.
The compiler has no idea what %d in your string is supposed to mean.
The compiler is _allowed_ to have no idea by the Standard. Passing
arguments to printf() that don't correspond with the format string
invokes undefined behaviour, which means that the implementation may or
may not notice, as it pleases. Had the Standard made this a constraint
violation, the implementation would have been required to diagnose this,
no matter which distinction between "compiler" and "library" many of
them currently make.
The C compiler doesn't "look into" strings,
This is misleading. For example, it certainly does look into them to
check for escape sequences. It is certainly also allowed to look into
printf()'s format string, and check the rest of its arguments; in fact,
some implementations do so.
Remember, printf could be overridden by your own code.
No, it couldn't. Again, _some_ implementations allow this; but in ISO C,
trying to override the Standard functions invokes undefined behaviour.
And in fact, it can have disastrous results if the rest of the library
happens to rely on that one function being the one they expect.
You could redefine printf to do something completely different and link
it into your code, which does not do anything at all with %d.
Not if you want it to run anywhere except on the implementation you
wrote it on, you can't.
printf is simply a library function, not a part of the language itself.


Again, in ISO C this distinction is to all intents and purposes devoid
of meaning. Either you have an ISO C implementation, or you do not.

Richard
Nov 15 '05 #9
Richard Bos <rl*@hoekstra-uitgeverij.nl> wrote:
[ Do not post without content. Google are bad enough netizens to do so,
but this does not mean you should emulate them. ]


ITYM "context"; only Skybuck posts without content :-)

--
Christopher Benson-Manica | I *should* know what I'm talking about - if I
ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
Nov 15 '05 #10
Robert Gamble wrote on 01/08/05 :
> int a =10;
> void *p = &a;
> printf("%d ", *p ); //error....why should it //be an error ?can't

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


The derefencement operator (*) returns a value of the type of the
pointer. If you derefence a void*, the type returned is void. What is a
value of type void ? It's not defined by the standard. From the C point
of view, it doesn't exist at all.

BTW, all the compilers I know used in conforming (so-called 'ansi')
mode forbid the dereferencement of a void *.

I know that gcc allows it in a non-conforming mode, considering the
type like a char. But IMO, it's just a nonsense.
--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.
Nov 15 '05 #11
Emmanuel Delahaye wrote:
Robert Gamble wrote on 01/08/05 :
>> int a =10;
>> void *p = &a;
>> printf("%d ", *p ); //error....why should it //be an error ?can't void is an incomplete type, a pointer to void is not. We are talking
about dereferencing a pointer to void.


The derefencement operator (*) returns a value of the type of the
pointer. If you derefence a void*, the type returned is void.


dereferencement? ;)

The result of dereferencing a void pointer is an expression of type
void, good so far.
What is a value of type void ? It's not defined by the standard. From the C
point of view, it doesn't exist at all.
Where do you come up with this value nonsense? What don't you
understand about "empty set of values"? Why do you think the result
must have a value?
BTW, all the compilers I know used in conforming (so-called 'ansi')
mode forbid the dereferencement of a void *.
Well then they are not conforming. The ability to legally dereference
void pointers has been upheld by the Commitee for over 10 years through
various defect reports and there is nothing in the Standard that does
anything but support the assertion that doing so is valid.
I know that gcc allows it in a non-conforming mode,


On all the versions of gcc I have access to (3.3.3, 3.3.5, 3.4.2,
3.4.3), the following compiles without error in "conforming mode":

int main (void) {
int i;
void *p = &i;
*p;
return 0;
}

$ gcc -Wall -W -ansi -pedantic void.c
void.c: In function `main':
void.c:4: warning: dereferencing `void *' pointer

The message given is what is called a warning, it is not an error, it
does not describe a statement that is "forbidden" and the program
compiles without issue. gcc warns about a lot of things that are not
in any way illegal (especially with all the options provided) as any
implementation is allowed to do. It still must properly translate the
program though, and it does.

Every other compiler I tried this on (cc on Tru64 Unix 4.0g, Tru64 Unix
5.1b and others) in strict-conforming mode did not even produce a
diagnostic and compiled the program successfully. Perhaps you could
provide some examples of "complaint" compilers that don't compile the
above program?

Robert Gamble

Nov 15 '05 #12
Robert Gamble wrote on 01/08/05 :
Every other compiler I tried this on (cc on Tru64 Unix 4.0g, Tru64 Unix
5.1b and others) in strict-conforming mode did not even produce a
diagnostic and compiled the program successfully. Perhaps you could
provide some examples of "complaint" compilers that don't compile the
above program?


int main (void)
{
int i;
void *p = &i;
*p = 1;
return 0;
}

<Borland C 3.1>
Compiling ..\MAIN.C:
Error ..\MAIN.C 5: Not an allowed type
Warning ..\MAIN.C 7: 'p' is assigned a value that is never used

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

I once asked an expert COBOL programmer, how to
declare local variables in COBOL, the reply was:
"what is a local variable?"
Nov 15 '05 #13
"Robert Gamble" <rg*******@gmail.com> writes:
[...]
On all the versions of gcc I have access to (3.3.3, 3.3.5, 3.4.2,
3.4.3), the following compiles without error in "conforming mode":

int main (void) {
int i;
void *p = &i;
*p;
return 0;
}

$ gcc -Wall -W -ansi -pedantic void.c
void.c: In function `main':
void.c:4: warning: dereferencing `void *' pointer

The message given is what is called a warning, it is not an error, it
does not describe a statement that is "forbidden" and the program
compiles without issue. gcc warns about a lot of things that are not
in any way illegal (especially with all the options provided) as any
implementation is allowed to do. It still must properly translate the
program though, and it does.
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.
Every other compiler I tried this on (cc on Tru64 Unix 4.0g, Tru64 Unix
5.1b and others) in strict-conforming mode did not even produce a
diagnostic and compiled the program successfully. Perhaps you could
provide some examples of "complaint" compilers that don't compile the
above program?


If a compiler in conforming mode doesn't produce a diagnostic for the
above program, we can conclude either that the code has no syntax
errors or constraint violations, or that the compiler is buggy.

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. On the other hand, it's certainly possible
to have a void expression in some contexts, as long as the result
isn't used; for example, a call to a void function is legal in an
expression statement.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #14
Emmanuel Delahaye wrote:
Robert Gamble wrote on 01/08/05 :
Every other compiler I tried this on (cc on Tru64 Unix 4.0g, Tru64 Unix
5.1b and others) in strict-conforming mode did not even produce a
diagnostic and compiled the program successfully. Perhaps you could
provide some examples of "complaint" compilers that don't compile the
above program?


int main (void)
{
int i;
void *p = &i;
*p = 1;
return 0;
}

<Borland C 3.1>
Compiling ..\MAIN.C:
Error ..\MAIN.C 5: Not an allowed type
Warning ..\MAIN.C 7: 'p' is assigned a value that is never used


Well of course that is wrong, dereferencing a void pointer does not
yield an lvalue silly. In the program I produced (which you
conveniently snipped) I dereferenced p, I didn't treat *p as an lvalue.
Nice try though.

Robert Gamble

Nov 15 '05 #15
Keith Thompson wrote:
"Robert Gamble" <rg*******@gmail.com> writes:
[...]
On all the versions of gcc I have access to (3.3.3, 3.3.5, 3.4.2,
3.4.3), the following compiles without error in "conforming mode":

int main (void) {
int i;
void *p = &i;
*p;
return 0;
}

$ gcc -Wall -W -ansi -pedantic void.c
void.c: In function `main':
void.c:4: warning: dereferencing `void *' pointer

The message given is what is called a warning, it is not an error, it
does not describe a statement that is "forbidden" and the program
compiles without issue. gcc warns about a lot of things that are not
in any way illegal (especially with all the options provided) as any
implementation is allowed to do. It still must properly translate the
program though, and it does.


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 in
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.
Every other compiler I tried this on (cc on Tru64 Unix 4.0g, Tru64 Unix
5.1b and others) in strict-conforming mode did not even produce a
diagnostic and compiled the program successfully. Perhaps you could
provide some examples of "complaint" compilers that don't compile the
above program?


If a compiler in conforming mode doesn't produce a diagnostic for the
above program, we can conclude either that the code has no syntax
errors or constraint violations, or that the compiler is buggy.

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:

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

I think we agree that this is clear.

'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.'

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.

'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.

'If an invalid value has been assigned to the pointer, the behavior of
the unary * operator is undefined.'

Thus, dereferencing an uninitialized void pointer or a void pointer
initialized to NULL would invoke undefined behavior.

The only thing I think is capable of being misunderstood here is
whether a void pointer "points to an object". If you think the
Standard says it does, then the following sentence would be an obvious
contradiction, a void type cannot be an lvalue.

Robert Gamble

Nov 15 '05 #16
Robert Gamble wrote:
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.

Robert Gamble

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.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 15 '05 #17
Joe Wright wrote:
Robert Gamble wrote:
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.

Robert Gamble

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.


While dereferencing a void pointer may not be very useful, it's not
undefined behavior. The nonsense is you and others who have no idea
what they are talking about, making assertions based on what they think
makes sense, not what the Standard or the Committee says. Can you
point to any place in the Standard that indicates that this is
undefined behavior? Why don't you take a look at DR #012 and DR #106
and come back here when you have found something in the Standard that
you have miscontrued to support your claim. (Sorry if this is coarse
but I am tired of arguing this point with people who refuse to support
their claims).

Robert Gamble

Nov 15 '05 #18
On Mon, 01 Aug 2005 20:43:32 -0400, Joe Wright wrote:
Robert Gamble wrote:
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).

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.

So I think that perhaps what you meant is that dereferencing an "anything"
pointer is nonsensical (what is an "anything"??), which I agree with.

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

Nov 15 '05 #19
"Robert Gamble" <rg*******@gmail.com> writes:
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]
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:

'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.
'If an invalid value has been assigned to the pointer, the behavior of
the unary * operator is undefined.'

Thus, dereferencing an uninitialized void pointer or a void pointer
initialized to NULL would invoke undefined behavior.

The only thing I think is capable of being misunderstood here is
whether a void pointer "points to an object". If you think the
Standard says it does, then the following sentence would be an obvious
contradiction, a void type cannot be an lvalue.


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?

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".)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #20
Keith Thompson <ks***@mib.org> writes:
[...]
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.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #21
Robert Gamble wrote:
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.

--
Chris "electric hedgehog" Dollin
predicting self-predictors' predictions is predictably unpredictable.
Nov 15 '05 #22
Richard Bos wrote:
Chris Dollin <ke**@hpl.hp.com> wrote:
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.
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.

--
Chris "electric hedgehog" Dollin
predicting self-predictors' predictions is predictably unpredictable.
Nov 15 '05 #23
Chris Dollin <ke**@hpl.hp.com> wrote:
Richard Bos wrote:
Chris Dollin <ke**@hpl.hp.com> wrote:
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?
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.


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
Nov 15 '05 #24
Joe Wright <jo********@comcast.net> wrote:
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
Nov 15 '05 #25
Robert Gamble wrote:
Chris Dollin wrote:
Robert Gamble wrote:
> Chris Dollin wrote:
>> maadhuu wrote:
>>
>> > hello, this is a piece of code ,which is giving an error.
>> > #include<stdio.h>
>> >
>> > int main()
>> > {
>> > int a =10;
>> > void *p = &a;
>> > printf("%d ", *p ); //error....why should it //be an error
>> > ?can't the
>> > compiler make out because //of %d that the pointer is supposed to
>> > refer to an integer ?? or is explicit type casting required ??
>>
>> *p is illegal because you are not permitted to dereference a void
>> pointer. That you clearly "intended" *p to be an int doesn't permit
>> the compiler to ignore the error.
>
> In this case the printf statement is incorrect, but simply
> dereferencing a valid void pointer is not illegal.
>
>> If *someVoidPointer *were* legal
>
> Which it is...
I beg to differ. It is not legal in standard C. Your very own quote
below says that `void` is an incomplete type, and incomplete types
cannot be dereferenced when I last looked.


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


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


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.

--
Chris "electric hedgehog" Dollin
predicting self-predictors' predictions is predictably unpredictable.
Nov 15 '05 #26
Richard Bos wrote:
Chris Dollin <ke**@hpl.hp.com> wrote:
Richard Bos wrote:
> 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?


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`.
> 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.


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.

--
Chris "electric hedgehog" Dollin
predicting self-predictors' predictions is predictably unpredictable.
Nov 15 '05 #27
On Tue, 02 Aug 2005 09:18:08 +0100, Chris Dollin wrote:
Robert Gamble wrote:
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.


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.

Nov 15 '05 #28
On Tue, 02 Aug 2005 04:43:00 +0000, Keith Thompson wrote:
"Robert Gamble" <rg*******@gmail.com> writes:
Keith Thompson wrote:

<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/...c8d77b7?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.

Nov 15 '05 #29
Keith Thompson wrote:
"Robert Gamble" <rg*******@gmail.com> writes:
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]
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:

'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.
'If an invalid value has been assigned to the pointer, the behavior of
the unary * operator is undefined.'

Thus, dereferencing an uninitialized void pointer or a void pointer
initialized to NULL would invoke undefined behavior.

The only thing I think is capable of being misunderstood here is
whether a void pointer "points to an object". If you think the
Standard says it does, then the following sentence would be an obvious
contradiction, a void type cannot be an lvalue.


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/wg...cs/dr_012.html
http://www.open-std.org/jtc1/sc22/wg...cs/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

Nov 15 '05 #30
Netocrat wrote:
On Tue, 02 Aug 2005 09:18:08 +0100, Chris Dollin wrote:
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.]

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.

--
Chris "electric hedgehog" Dollin
predicting self-predictors' predictions is predictably unpredictable.
Nov 15 '05 #31
On Tue, 02 Aug 2005 14:39:57 +0100, Chris Dollin wrote:
Netocrat wrote:
On Tue, 02 Aug 2005 09:18:08 +0100, Chris Dollin wrote:
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;?

&*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/...b7078dafa8d9ec

In particular Robert Gamble's fourth post; Douglas Gwyn's 2nd post and
my reply.
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?

<snip rest>

Nov 15 '05 #32
Netocrat wrote:
On Tue, 02 Aug 2005 14:39:57 +0100, Chris Dollin wrote:
Netocrat wrote:
On Tue, 02 Aug 2005 09:18:08 +0100, Chris Dollin wrote:
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.
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/...b7078dafa8d9ec
In particular Robert Gamble's fourth post; Douglas Gwyn's 2nd post and
my reply.
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?

--
Chris "electric hedgehog" Dollin
predicting self-predictors' predictions is predictably unpredictable.
Nov 15 '05 #33
Robert Gamble wrote:
Keith Thompson wrote:
"Robert Gamble" <rg*******@gmail.com> writes:
Keith Thompson wrote:
<snip> 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.


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.

Nov 15 '05 #34
Chris Dollin wrote:
Netocrat wrote:
On Tue, 02 Aug 2005 14:39:57 +0100, Chris Dollin wrote:
Netocrat wrote:
On Tue, 02 Aug 2005 09:18:08 +0100, Chris Dollin wrote:
<snip>
[p being of type void *]
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.

<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.)"

Nov 15 '05 #35
Netocrat wrote:
Chris Dollin wrote:
Netocrat wrote:
> On Tue, 02 Aug 2005 14:39:57 +0100, Chris Dollin wrote:
>> Netocrat wrote:
>>> On Tue, 02 Aug 2005 09:18:08 +0100, Chris Dollin wrote:
<snip>
[p being of type void *]
> 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.

<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, 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.

--
Chris "electric hedgehog" Dollin
predicting self-predictors' predictions is predictably unpredictable.
Nov 15 '05 #36
Chris Dollin wrote:
Netocrat wrote:
Chris Dollin wrote:
Netocrat wrote:
> On Tue, 02 Aug 2005 14:39:57 +0100, Chris Dollin wrote:
>> Netocrat wrote:
>>> On Tue, 02 Aug 2005 09:18:08 +0100, Chris Dollin wrote:
<snip>
[p being of type void *]
> 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.

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

Nov 15 '05 #37
Netocrat wrote:
.... 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?

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 15 '05 #38
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.

--
pete
Nov 15 '05 #39
Keith Thompson <ks***@mib.org> writes:
"Robert Gamble" <rg*******@gmail.com> writes:
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.
Nov 15 '05 #40
"Robert Gamble" <rg*******@gmail.com> writes:
Keith Thompson wrote:
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.


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."
Nov 15 '05 #41
CBFalconer <cb********@yahoo.com> writes:
Netocrat wrote:

... 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?


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.
Nov 15 '05 #42
Netocrat <ne******@dodo.com.au> wrote:
Chris Dollin wrote:
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.
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.


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.

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 15 '05 #43
Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
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.

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 15 '05 #44
Netocrat wrote:
On Mon, 01 Aug 2005 20:43:32 -0400, Joe Wright wrote:

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

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 15 '05 #45
On Wed, 03 Aug 2005 21:03:04 -0400, Joe Wright wrote:
Netocrat wrote:
On Mon, 01 Aug 2005 20:43:32 -0400, Joe Wright wrote:
<snip>
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.
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?


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.
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?


Off the top of my head I can't point to another context for void.
Perhaps I should have used singular.
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.


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.

Nov 15 '05 #46
"S.Tobias" <si***@FamOuS.BedBuG.pAlS.INVALID> writes:
Tim Rentsch <tx*@alumnus.caltech.edu> wrote:
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.
Nov 15 '05 #47
"Netocrat" <ne******@dodo.com.au> writes:
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.
Nov 15 '05 #48
Netocrat <ne******@dodo.com.au> wrote:
On Wed, 03 Aug 2005 21:03:04 -0400, Joe Wright wrote:
Netocrat wrote:
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?


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

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.


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'.
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.


I don't remember doing that. `*obj' is type void, and therefore
is *not* 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;


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.

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 15 '05 #49
On Thu, 04 Aug 2005 08:38:28 +0000, S.Tobias wrote:
Netocrat <ne******@dodo.com.au> wrote: <snip>
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'?


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).

<snip>
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.


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.

<snip> 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.

Nov 15 '05 #50

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

9 posts views Thread by Juggernaut | last post: by
9 posts views Thread by Alex Vinokur | last post: by
4 posts views Thread by brianhray | last post: by
18 posts views Thread by hyderabadblues | last post: by
35 posts views Thread by Roman Mashak | last post: by
8 posts views Thread by brad2000 | last post: by
160 posts views Thread by raphfrk | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.