Void questions

F

Francis Moreau

Hello,

I have some stupids questions about void type and pointer to void.

Actually I've always known the answers but I wanted to find the
revelant parts in the C specs and fails.

The first one is about dereferencing a void pointer. It's just
forbidden but when reading 6.5.3.2 about indirection operators, I
can't find anything that states it.

The second one is about arithmetic on void *. I read section 6.5.6
about Additive operators but it doesn't state that arithmetic on void
* is forbidden. I thought that was the case since void * is a pointer
to an incomplete type.

The last question is about the section 6.2.5.26 which states: "A
pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.". I'm not sure to
understand why the spec speaks about alignement requierements since a
pointer to void cannot be dereferenced.

Thanks for help.
 
P

Phred Phungus

Francis said:
Hello,

I have some stupids questions about void type and pointer to void.

Actually I've always known the answers but I wanted to find the
revelant parts in the C specs and fails.

I doubt that you mean to say this. I don't think you know how to use
english verbs correctly.

$.02
 
F

Francis Moreau

I doubt that you mean to say this.  I don't think you know how to use
english verbs correctly.

$.02

yes, probably this is better: "Actually I know the answers but I would
like to find the revelant parts in the C specs but have failed so
far."

Is this better ?
 
R

Richard Tobin

Francis Moreau said:
The first one is about dereferencing a void pointer. It's just
forbidden but when reading 6.5.3.2 about indirection operators, I
can't find anything that states it.

Void is an incomplete type, so it should be covered by a prohibition
on applying * to incomplete types. I can't see anything explicit
about this.

You might argue that it's forbidden becuase 6.5.3.2 says the
result would be of type void, and there are no objects of type
void.

The wording in 6.5.3.2 is odd; it says "If an invalid value has been
assigned to the pointer, the behaviour ... is undefined". Why
"assigned to"? It isn't necessarily a variable.
The last question is about the section 6.2.5.26 which states: "A
pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.". I'm not sure to
understand why the spec speaks about alignement requierements since a
pointer to void cannot be dereferenced.

Read the footnote.

-- Richard
 
B

Ben Bacarisse

Francis Moreau said:
I have some stupids questions about void type and pointer to void.

There are no stupid questions.
Actually I've always known the answers but I wanted to find the
revelant parts in the C specs and fails.

The first one is about dereferencing a void pointer. It's just
forbidden but when reading 6.5.3.2 about indirection operators, I
can't find anything that states it.

That's because it is not "forbidden". The C standard does not say
that anything is "forbidden", but a close match is those things that
are constraint violations (roughly speaking, compile-time errors) and
applying * to a void * is not one of these.

Some uses of * on void pointer are perfectly valid: &*vp is
well-defined for example.

Other clauses tell us that the result is of type void and that we
can't use the (non-existent) value of this type for any purpose at
all, which is enough for me. One can go further, in that void is not
an object type so one can argue that 6.5.3.2 p4 does not give a
meaning to * when applied to a void *. [The phrase "points to an
object" is not quite the same as "is a pointer to an object type that
points to an object" so, personally, I'd prefer a plain statement of
UB is that is what was intended.]
The second one is about arithmetic on void *. I read section 6.5.6
about Additive operators but it doesn't state that arithmetic on void
* is forbidden. I thought that was the case since void * is a pointer
to an incomplete type.

The clause you cite does forbid it; and for exactly the reason you
cite!. It is, in fact, a constraint violation because void is not an
object type:

Constraints

2 For addition, either both operands shall have arithmetic type, or
one operand shall be a pointer to an object type and the other
shall have integer type.
The last question is about the section 6.2.5.26 which states: "A
pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.". I'm not sure to
understand why the spec speaks about alignement requierements since a
pointer to void cannot be dereferenced.

I am not sure the alignment part has any effect (the representation
part is important). I suspect the standard would be the same if the
words "and alignment requirements" were deleted. The standard does
not define exactly what "having the same representation" means, so the
extra words do help to make it certain that a void * can never require
more or less alignment than a char *.
 
F

frank

Francis said:
yes, probably this is better: "Actually I know the answers but I would
like to find the revelant parts in the C specs but have failed so
far."

Is this better ?

Yes. If it's to be english, then you'll need to divest yourself
somewhat of the initial adverb, but if it's failing with C, then it's a
language we all know. :)

Cheers,
--
 
E

Eric Sosman

Hello,

I have some stupids questions about void type and pointer to void.

Actually I've always known the answers but I wanted to find the
revelant parts in the C specs and fails.

The first one is about dereferencing a void pointer. It's just
forbidden but when reading 6.5.3.2 about indirection operators, I
can't find anything that states it.

6.5.3.2p4 specifies what happens when dereferencing a
pointer "to a function" or "to an object." A void* obviously
can't do the first. What you're probably missing is that it
also can't do the second, because of 6.2.5p1: "[...] Types are
partitioned into object types [...], function types [...], and
incomplete types [...]" A void* is a pointer to an incomplete
type, not a pointer to an object type, so the language of
6.5.3.2p4 doesn't apply. The outcome of a dereference is
undefined not because the Standard says so explicitly, but
because it doesn't say anything to define it (see 4p2).
The second one is about arithmetic on void *. I read section 6.5.6
about Additive operators but it doesn't state that arithmetic on void
* is forbidden. I thought that was the case since void * is a pointer
to an incomplete type.

You're right, and the reasoning is the same as before.
6.5.6p2 requires that the pointer be "to an object type," which
leaves out incomplete types. (This is in a Constraints section,
so the implementation must diagnose the attempt).
The last question is about the section 6.2.5.26 which states: "A
pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.". I'm not sure to
understand why the spec speaks about alignement requierements since a
pointer to void cannot be dereferenced.

It's speaking of the alignment requirements of the pointer
itself, not of the thing pointed to. A void* variable is like
any other (non-bit-field) variable: double, int**, short, or
whatever, and as such may have some kind of alignment requirement.
The Standard says that the alignment requirement for a void* is
the same as that for a char* (presumably because char* was "the
generic pointer" before void* was introduced to the language, and
the 1989 Standard didn't want to mess up existing code unduly).
 
B

Ben Bacarisse

Eric Sosman said:
Hello,

I have some stupids questions about void type and pointer to void.

Actually I've always known the answers but I wanted to find the
revelant parts in the C specs and fails.

The first one is about dereferencing a void pointer. It's just
forbidden but when reading 6.5.3.2 about indirection operators, I
can't find anything that states it.

6.5.3.2p4 specifies what happens when dereferencing a
pointer "to a function" or "to an object." A void* obviously
can't do the first. What you're probably missing is that it
also can't do the second, because of 6.2.5p1: "[...] Types are
partitioned into object types [...], function types [...], and
incomplete types [...]" A void* is a pointer to an incomplete
type, not a pointer to an object type, so the language of
6.5.3.2p4 doesn't apply.

I'm not entirely persuaded by this because the phrase "points to an
object" is not as precise as I'd like. For example in 6.2.4 p2 we
read:

"The value of a pointer becomes indeterminate when the object it
points to reaches the end of its lifetime."

This is surely meant to cover a void * pointing to an object, but if
we take your strict reading of pointing to an object a void * can't
point to an object. I am pretty sure that your reading of 6.5.3.2 p4
is the one that was intended, but I'd prefer it to be a little more
explicit.

<snip>
 
N

Nick

Richard Heathfield said:
Actually, there are very many stupid questions. But these weren't
three of them.

Is "are there any stupid questions?" a stupid question? How about that one?
 
R

Richard Bos

Phred Phungus said:
I doubt that you mean to say this. I don't think you know how to use
english verbs correctly.

You shouldn't be talking, frankie-boy, especially since you don't know
how to capitalise "English".

Richard
 
F

Francis Moreau

I have some stupids questions about void type and pointer to void.
Actually I've always known the answers but I wanted to find the
revelant parts in the C specs and fails.
The first one is about dereferencing a void pointer. It's just
forbidden but when reading 6.5.3.2 about indirection operators, I
can't find anything that states it.

     6.5.3.2p4 specifies what happens when dereferencing a
pointer "to a function" or "to an object."  A void* obviously
can't do the first.  What you're probably missing is that it
also can't do the second, because of 6.2.5p1: "[...] Types are
partitioned into object types [...], function types [...], and
incomplete types [...]"  A void* is a pointer to an incomplete
type, not a pointer to an object type, so the language of
6.5.3.2p4 doesn't apply.  The outcome of a dereference is
undefined not because the Standard says so explicitly, but
because it doesn't say anything to define it (see 4p2).

Ah yes, this is what I was missing: an incomplete type is not the same
as an object type.
     You're right, and the reasoning is the same as before.
6.5.6p2 requires that the pointer be "to an object type," which
leaves out incomplete types.
Agreed.

 (This is in a Constraints section,
so the implementation must diagnose the attempt).

Strangely enough, gcc doesn't:

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

Compiling this with: 'gcc -Wall main.c', doesn't produce any warnings/
errors.
     It's speaking of the alignment requirements of the pointer
itself, not of the thing pointed to.  A void* variable is like
any other (non-bit-field) variable: double, int**, short, or
whatever, and as such may have some kind of alignment requirement.
The Standard says that the alignment requirement for a void* is
the same as that for a char* (presumably because char* was "the
generic pointer" before void* was introduced to the language, and
the 1989 Standard didn't want to mess up existing code unduly).

Again thank you for explanations.
 
F

Francis Moreau

    6.5.3.2p4 specifies what happens when dereferencing a
pointer "to a function" or "to an object."  A void* obviously
can't do the first.  What you're probably missing is that it
also can't do the second, because of 6.2.5p1: "[...] Types are
partitioned into object types [...], function types [...], and
incomplete types [...]"  A void* is a pointer to an incomplete
type, not a pointer to an object type, so the language of
6.5.3.2p4 doesn't apply.

I'm not entirely persuaded by this because the phrase "points to an
object" is not as precise as I'd like.  For example in 6.2.4 p2 we
read:

  "The value of a pointer becomes indeterminate when the object it
  points to reaches the end of its lifetime."

This is surely meant to cover a void * pointing to an object, but if
we take your strict reading of pointing to an object a void * can't
point to an object.  I am pretty sure that your reading of 6.5.3.2 p4
is the one that was intended, but I'd prefer it to be a little more
explicit.

I agree that some others sections may be confusing, specially if you
miss 6.2.5p1 as I did.

Thanks all for your help.
 
K

Keith Thompson

Francis Moreau said:
Strangely enough, gcc doesn't:

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

Compiling this with: 'gcc -Wall main.c', doesn't produce any warnings/
errors.
[...]

Right, "gcc -Wall" is not a conforming C compiler.

Adding the "-pedantic" option causes it to warn about the above code:

warning: pointer of type `void *' used in arithmetic

A non-fatal warning is a valid response to a constraint violation.

(I don't think "-pedantic" by itself is sufficient to cause gcc to
become a conforming C compiler.)
 
T

Tim Rentsch

Francis Moreau said:
The last question is about the section 6.2.5.26 which states: "A
pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.". I'm not sure to
understand why the spec speaks about alignement requierements since a
pointer to void cannot be dereferenced.

Note that alignment requirements mentioned here are for
the actual _pointers_, not for what's being pointed to.
A (char*) variable and a (void*) variable have the same
alignment requirement (which is unrelated to the alignment
of (char)).
 
T

Tim Rentsch

Eric Sosman said:
Hello,

I have some stupids questions about void type and pointer to void.

Actually I've always known the answers but I wanted to find the
revelant parts in the C specs and fails.

The first one is about dereferencing a void pointer. It's just
forbidden but when reading 6.5.3.2 about indirection operators, I
can't find anything that states it.

6.5.3.2p4 specifies what happens when dereferencing a
pointer "to a function" or "to an object." A void* obviously
can't do the first. What you're probably missing is that it
also can't do the second, because of 6.2.5p1: "[...] Types are
partitioned into object types [...], function types [...], and
incomplete types [...]" A void* is a pointer to an incomplete
type, not a pointer to an object type, so the language of
6.5.3.2p4 doesn't apply.

I believe this interpretation is a misreading. The Standard means
what it says, if the pointer "points to an object" is talking about
where the pointer points, not what type of pointer it is. And this
is there to rule out null pointers, which don't point to an object.
Pointers to incomplete types (and that aren't null pointers, or
point one past the end of an array) still point to objects.

Why then is it undefined behavior? Pray read on...

The outcome of a dereference is
undefined not because the Standard says so explicitly, but
because it doesn't say anything to define it (see 4p2).

Indirecting through a pointer to an incomplete type (not just (void))
is undefined behavior because 6.3.2.1p2 says so explicitly:

Except when it is the operand of the sizeof operator, the unary
& operator, the ++ operator, the -- operator, or the left
operand of the . operator or an assignment operator, an lvalue
that does not have array type is converted to the value stored
in the designated object (and is no longer an lvalue). If the
lvalue has qualified type, the value has the unqualified version
of the type of the lvalue; otherwise, the value has the type of
the lvalue. If the lvalue has an incomplete type and does not
have array type, the behavior is undefined.
 
T

Tim Rentsch

Richard Heathfield said:
No. But here's an example of a stupid question: "Will the trolls ever
get a clue?"

How about whether you will ever get a clue? I know
some people think that's a stupid question.

Stop being such a shit stirrer.
 
T

Tim Rentsch

Francis Moreau said:
The first one is about dereferencing a void pointer. It's just
forbidden but when reading 6.5.3.2 about indirection operators, I
can't find anything that states it.

My answer to this question is given in a response to
Eric Sosman's posting.
 
F

Francis Moreau

    6.5.3.2p4 specifies what happens when dereferencing a
pointer "to a function" or "to an object."  A void* obviously
can't do the first.  What you're probably missing is that it
also can't do the second, because of 6.2.5p1: "[...] Types are
partitioned into object types [...], function types [...], and
incomplete types [...]"  A void* is a pointer to an incomplete
type, not a pointer to an object type, so the language of
6.5.3.2p4 doesn't apply.

I believe this interpretation is a misreading.  The Standard means
what it says, if the pointer "points to an object" is talking about
where the pointer points, not what type of pointer it is.

I know that my English sucks (as someone pointed out) but I'm not
convinced about what you stated:

Here's the beginning of 6.2.5p1:

The meaning of a value stored in an object or returned by a
function is determined by the type of the expression used to
access it. Types are partitioned into...

Why is the spec so hard to read ?!

[snip]
 
B

Ben Bacarisse

Francis Moreau said:
Eric Sosman said:
On 2/2/2010 4:34 AM, Francis Moreau wrote:
Hello,
I have some stupids questions about void type and pointer to void.
Actually I've always known the answers but I wanted to find the
revelant parts in the C specs and fails.
The first one is about dereferencing a void pointer. It's just
forbidden but when reading 6.5.3.2 about indirection operators, I
can't find anything that states it.
    6.5.3.2p4 specifies what happens when dereferencing a
pointer "to a function" or "to an object."  A void* obviously
can't do the first.  What you're probably missing is that it
also can't do the second, because of 6.2.5p1: "[...] Types are
partitioned into object types [...], function types [...], and
incomplete types [...]"  A void* is a pointer to an incomplete
type, not a pointer to an object type, so the language of
6.5.3.2p4 doesn't apply.

I believe this interpretation is a misreading.  The Standard means
what it says, if the pointer "points to an object" is talking about
where the pointer points, not what type of pointer it is.

I know that my English sucks (as someone pointed out) but I'm not
convinced about what you stated:

Here's the beginning of 6.2.5p1:

The meaning of a value stored in an object or returned by a
function is determined by the type of the expression used to
access it. Types are partitioned into...

Why is the spec so hard to read ?!

What is the connection between your quote and the topic? As I read
it, the issue is whether a void * can be said to "point to an object"
despite the undisputed fact that a void * is a pointer to an
incomplete type not a pointer to an object type.

I.e. is it reasonable to say that after

int i = 42;
void *vp = &i;

vp does or does not point to i? I can see both sides, but I come down
with Tim on this one. My reason is that the standard uses the phrase
loosely somewhere else; specifically "6.2.4 Storage durations of
objects" paragraph 2:

2 The lifetime of an object is the portion of program execution
during which storage is guaranteed to be reserved for it. An
object exists, has a constant address and retains its last-stored
value throughout its lifetime. If an object is referred to outside
of its lifetime, the behavior is undefined. The value of a pointer
becomes indeterminate when the object it points to reaches the end
of its lifetime.

This clause would not apply to vp in either of these two situations:

void *vp; { int i; vp = &i; }; /* is vp indeterminate? */

or

void *vp = malloc(1); free(vp); /* is vp indeterminate? */

if the phrase were not to taken rather loosely. I am pretty sure that
in both these cases the intent was that 6.2.4 p2 would apply. Such
arguments are not strong, I agree, but other than "plain reading" I
have nothing better right now.

In summary, the distinction between a pointer that "points to an
object" and one that is of "pointer to object type" is fussy but
significant here.
 
T

Tim Rentsch

Joe Wright said:
Tim Rentsch wrote:

[ much snippage ]
I believe this interpretation is a misreading. The Standard means
what it says, if the pointer "points to an object" is talking about
where the pointer points, not what type of pointer it is.

Only in the case of void*. All valid pointers to objects have type.

Surely you realize that (void) is a type. A (void*) pointer
points to something of type (void). The type (void) is
unusual in several respects, but it is still a type.

"Pointers to incomplete types" points to what objects? An object being
a region of storage etc..

Here is the last sentence of 6.2.5p1:

Types are partitioned into object types (types that fully
describe objects), function types (types that describe
functions), and incomplete types (types that describe objects
but lack information needed to determine their sizes).

Note the last part. Incomplete types still describe objects. Pointers
to incomplete types still point to objects, it just isn't known how
big the objects are.
 

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

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top