Email List: Xaustin-group-lX
[All Lists]

RE: [1003.1(2008)/Issue 7 0000074]: Pointer Types Problem

To: "Wojtek Lerch" <wojtek@xxxxxxx>
Subject: RE: [1003.1(2008)/Issue 7 0000074]: Pointer Types Problem
From: "Schwarz, Konrad" <konrad.schwarz@xxxxxxxxxxx>
Date: Fri, 3 Jul 2009 09:55:25 +0200
Cc: <austin-group-l@xxxxxxxxxxxxx>
References: <e26e5335cda9d0dfe49395e6115066fe@xxxxxx> <1730938080F74546ACC51CB65BA00565@xxxxxx> <20090702094404.GA28393@xxxxxx> <4A4CC239.2040603@xxxxxx> <5030E566C603DA449D6B4C060CE529B73A8F37@MCHP7RDA.ww002.siemens.net> <4A4D2366.9090904@xxxxxx>
Thread-index: Acn7WujWGeMqB9+ARVOvty8p0UGcfwAS+nFQ
Thread-topic: [1003.1(2008)/Issue 7 0000074]: Pointer Types Problem
> From: Wojtek Lerch [mailto:wojtek@xxxxxx] 
> >     A pointer to <b>void</b> may be converted to or from a pointer
> > to any function type.
> 
> You would want to allow converting *any* void pointers to function 
> pointers?  I don't think that's necessary.  I think it's 
> better to let 
> it be undefined behaviour, except for void pointers that are 
> converted 
> pointers to function.  That would make it consistent with conversions 
> from void* to other pointer types in standard C -- they're undefined 
> unless you have made sure that you're not violating any alignment 
> requirements.  (And since alignment requirements are 
> unspecified, it's 
> hard to satisfy them other than by ensuring that your void pointer 
> indeed points to an object of the correct type.  Or was returned by 
> malloc().)

In the C standard, paragraph 1 states that the conversions void * to
other object/incomplete type are allowed, paragraph 7 states what
happens
if the pointer is not aligned.  In analogy, my first paragraph states
that the conversions between void * and function pointers are allowed,
my second paragraph states legal uses of the converted pointer
(comparison with a NULL pointer and conversion back to a function type).
Everything else is undefined.

Paragraph 8 already states that if a pointer to one function type is
used to call a function of non-compatible type, the behavior is
undefined.

> >>I don't think it's a good idea to introduce unusual 
> >>restrictions on what 
> >>the void* pointer can be converted to.  Can I convert it to a "void 
> >>const*"?  What about a "void *const"?  Why would it need to 
> >>be undefined 
> >>behaviour to convert it to a char*, even though standard C 
> intends to 
> >>allow converting any valid void* pointer to char*?
> > 
> > 
> > I think these questions are largely answered by paragraph 2 of the
> > section quoted above:
> > 
> >     For any qualifier q, a pointer to a non-q-qualified type may be
> > converted to a pointer to
> >     the q-qualified version of the type; the values stored in the
> > original and converted pointers
> >     shall compare equal.
> 
> I don't think it's clear that that paragraph applies.  Keep 
> in mind that 
> we're talking about programs that have invoked undefined behaviour 
> according to the C standard (by converting a function pointer 
> to a void 
> pointer).   This new kind of void* values that POSIX is trying to 
> introduce does not exist in standard C; if POSIX specifically 
> says that 
>   the behaviour is undefined if such a value is converted to 
> a pointer 
> to an object or an incomplete type, I would tend to interpret that as 
> overriding what C says about conversions of normal pointers 
> -- not the 
> other way around.

I think POSIX should continue to allow all these conversions.  Thus,
it can remain silent on the issue.  The only important things are that
pointers to objects have the same size as pointers to functions and
that NULL pointers are mapped to NULL pointers.

> OK, but still, it's not obvious to me that this necessarily 
> applies to 
> conversions that have undefined behaviour in standard C.

According to 3.4.3, in ANSI C, undefined behavior is "behavior,
upon use of a nonportable or erroneous program construct [...]
for which this International Standard imposes no requirements."

What POSIX is doing here is making one instance of undefinded behavior
defined.  Everything else continues to apply as usual.

> Normally a void* pointer can be compared to another void* pointer; if 
> you make it undefined behaviour for some valid pointers, you'll be 
> introducing an inconsistency that people will tend to forget 
> about.  My 
> feeling is that it would be better to allow comparing but 
> discourage it 
> by saying that the result is unspecified.

Section 6.3.2.3 only defines the equality of pointers
to non-void type.  However, 6.5.9, Equality Operators,
specifies that comparison of an object pointer with a
void pointer converts the void pointer to the type of
the object pointer.

So POSIX would have to specify that the analogous
conversion would need to be done for function pointers,
if it wanted to allow arbitrary comparisons of (uncasted)
void pointers with function pointers.

However, I suspect that at least
some compilers emit a warning here---changing this
would require changes to those compilers.  This is
probably not warranted.

> (I would still prefer to say that it may accidentally happen 
> to compare 
> equal to some object pointers, because that's consistent with 
> how C says 
> that a pointer to object may accidentally compare equal to a pointer 
> past the end of some unrelated array.  But I could live with simply 
> "unspecified", even though I don't like the idea of it returning any 
> value other than 0 or 1, or the idea that it might return different 
> values when you compare the same two pointers twice.)

See my comment at the bottom.

> >     If a pointer to any function type, converted to a pointer to
> > <b>void</b>,
> >     is used for any purpose other than conversion back to a pointer
> > to a
> >     function or comparison with a null pointer, the behavior is
> > undefined.
> 
> Comparison with a null pointer, or specifically with a null pointer 
> cstant?

For consistency with the rest of the C standard, which alows
comparing function pointers with null pointers, not just
null pointer constants, a null pointer.  (See paragraph 3).

On the other hand, paragraph 4 says that conversion of a null pointer
to another pointer type yields a null pointer of that type.  Any
two null pointers shall compare equal.  So null pointers are covered
already.

> Can't it be used in an assignment?  In a compound literal?  
> Passed to a 
> function?  Returned from a function?  Used to initialize a variable? 
> Converted to void?  To _Bool?  To another function pointer 
> stored in a 
> void*?

You are right, my second paragraph is too limiting.  Perhaps it
would suffice to say that the result of converting a function
designator to a void pointer results in an invalid object pointer,
similarly, the result of converting the address of an object to a
function pointer results in an invalid function pointer.

Additionally, it might be worth stating that conversion of a function
pointer
to an intptr_t or uintptr_t and back will result in a value equal to the
original pointer.

<Prev in Thread] Current Thread [Next in Thread>