something to do with void *

M

maadhuu

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

Chris Dollin

maadhuu said:
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.
 
R

Robert Gamble

Chris said:
*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
 
C

Christopher Benson-Manica

maadhuu said:
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.
 
C

Chris Dollin

Robert said:
In this case the printf statement is incorrect, but simply
dereferencing a valid void pointer is not illegal.


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

Jonathan Bartlett

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
 
R

Richard Bos

Chris Dollin said:
Robert said:
Chris said:
[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
 
R

Robert Gamble

Chris said:
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.
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
 
R

Richard Bos

[ 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
 
C

Christopher Benson-Manica

Richard Bos said:
[ 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 :)
 
E

Emmanuel Delahaye

Robert Gamble wrote on 01/08/05 :
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.
 
R

Robert Gamble

Emmanuel said:
Robert Gamble wrote on 01/08/05 :

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
 
E

Emmanuel Delahaye

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?"
 
K

Keith Thompson

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

Robert Gamble

Emmanuel said:
Robert Gamble wrote on 01/08/05 :

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
 
R

Robert Gamble

Keith said:
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.
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
 
J

Joe Wright

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.




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

Robert Gamble

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




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
 
N

Netocrat

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.


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

Keith Thompson

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

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

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

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

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

[snip]
Well, lets break it down then:

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

I think we agree that this is clear.
Sure.

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

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

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

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

I think I agree -- but on the other hand, one could argue that a
result is a value, and since there are no values of type void, we have
a contradiction.
'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".)
 

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