Topic: Does Casting to (const void *) in a printf Produce Undefined Behavior?


Author: hendrik@vedge.com (Hendrik Boom)
Date: Mon, 09 Aug 1993 13:07:48 GMT
Raw View
diamond@jit.dec.com (Norman Diamond) writes:
:
: In article <23luro$io5@news.cs.tu-berlin.de> jutta@cs.tu-berlin.de (Jutta Degener) writes:
: >diamond@jit.dec.com (Norman Diamond) writes:
: >> In article <...> jackw@bnr.ca (John Davison in care of Jack Wasserman) writes:
: >>> void const *
:
: >> This doesn't have to work.  The implementation's representation of a
: >> pointer to const void doesn't have to be the same as the implementation's
: >> representation of a pointer to plain void.
:
: >Has too.   From ANSI section 3.1.2.5, Types:
: ># Similarly, pointers to qualified or unqualified versions of
: ># compatible types shall have the same representation and
: ># alignment requirements.[16]
:
: Hmmmmmmmmmmmm.  I almost want to ask myself angrily how I could forget that,
: but in fact I know why I forgot.
:
: The committee recently issued an interpretation ruling that pointer to int
: and pointer to int do not have to have the same representation.  Int and
: int are compatible because their types are the same, so pointer to int and
: pointer to int are pointers to compatible types, but if one is pointing to
: the first element of an array of 5 ints and one is pointing to the first
: element of an array of 10 ints then their representations do not have to
: be the same.
:
: I give up.
:

This kind of obscurity is exactly why there should have been a more formal
definition of C, and why C++ should have a formal definition, too..
I long for something of at least the precision of the Algol 68 Revised Report.
Their use of English in the semantics was essentially the use of a formal
language which just happened to be a true subset of English.

The VDM and C standards are incomprehensible, although for opposite reasons.


: --
:  <<  If this were the company's opinion, I would not be allowed to post it.  >>
: A program in conformance will not tend to stay in conformance, because even if
: it doesn't change, the standard will.       Force = program size * destruction.
: Every technical corrigendum is met by an equally troublesome new defect report.








--
-------------------------------------------------------
Try one or more of the following addresses to reply.
at work: hendrik@vedge.com,  iros1!vedge!hendrik
at home: uunet!ozrout!topoi!hendrik




Author: hendrik@vedge.com (Hendrik Boom)
Date: Mon, 09 Aug 1993 13:13:05 GMT
Raw View
volpe@bart.crd.ge.com (Christopher R. Volpe) writes:
: In article <23nlde$25q@usenet.pa.dec.com>, diamond@jit.dec.com (Norman Diamond) writes:
: |>
: |> I give up.
:
: You and me both. (Now where'd I put that Fortran compiler...)
:

No. To get away with that joke you must be able to explain
second-level definition of FORTRAN variables.

: --
: ==================
: Chris Volpe
: G.E. Corporate R&D
: volpecr@crd.ge.com
--
-------------------------------------------------------
Try one or more of the following addresses to reply.
at work: hendrik@vedge.com,  iros1!vedge!hendrik
at home: uunet!ozrout!topoi!hendrik




Author: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe)
Date: 11 Aug 93 07:18:49 GMT
Raw View
In article <CBBy1r.Bz6@x.co.uk>, clive@x.co.uk (Clive Feather) writes:
> For example, consider:
>
>     int a [5][5];
>
>     struct fred
>     {
>         double d;
>         int i1 [10];
>         int i2 [10];
>     }
>     f, *pf;
>     pf = malloc (sizeof f + 10 * sizeof (int));
>
> Do you believe a [1][7] should be a legal expression ?

NO, because running off the end of a[1] may run into a[2]

> Do you believe f.i1 [15] should be a legal expression ?

NO, because running off the end of f.i1 may run into f.i2;
    we cannot make use of that because the compiler may insert padding.
    So we can't predict what degree of overlap there is.

> Do you believe f.i2 [15] should be a legal expression ?

YES, because the rule for malloc guarantees that there _is_ safe
     space after f.i2[] (it exists and we can address it via char*)
     which cannot overlap any declared object or field.

> Do you believe *pf->i1 [15] should be a legal expression ?

NO, because it's the same situation as f.i1[15]

> Do you believe *pf->i2 [15] should be a legal expression ?

YES, because it's the same situation as f.i2[15]

> If the answer to all of these is "no", you agree with the committee.
> If the answer to all of these is "yes", you believe in "largest object view".
> If not all your answers are the same, why ?

Because I am using a very simple model: a[i] should be illegal if it might
access space that does not exist or if it might access the "wrong" object.
Neither applies to the struct hack.

(In Ada, I would adopt a far stricter rule: declared bounds, no more and
no less.  But then, in Ada I can ask for exactly what I want.)

Once upon a time the C committee had a guiding principle that it wasn't
their job to break existing working code if they could reasonably avoid
breaking it.  The struct hack _was_ used in a great deal of existing
working code.  If people are going to start coming up with interpretations
that rule out existing practice, I'm going to stop being grateful for the
standard.

--
Richard A. O'Keefe; ok@goanna.cs.rmit.oz.au; RMIT, Melbourne, Australia.




Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Thu, 5 Aug 1993 15:46:15 GMT
Raw View
In article <CBAErp.3M1@x.co.uk>, clive@x.co.uk (Clive Feather) writes:
|> In article <CB8LJn.Ju4@crdnns.crd.ge.com> volpe@ausable.crd.ge.com writes:
|> > The Committee is on drugs. :-(
|>
|> This is libelous. You might not agree with the interpretation, but that
|> is no reason to be insulting.

Sorry if my remark offended you or anyone else. It was just an expression,
not a literal accusation.

|>
|> > Is there a procedure for getting an interpretation ruling repealed?
|>
|> Persuade your national member body, whoever that may be, to vote against

I assume you mean ANSI?

|> the Record of Response when it is placed in front of ISO/IEC/JTC1/SC22
|> (it hasn't been yet, so it isn't an official response yet). You will need

Hmmm. What actually has happened so far then if the ruling is not official?
What's the process? Who issued the ruling originally, if not the final
authority?

|> to get at least two, and preferably three, NO votes, so you will need to
|> get several member bodies involved.
|>
|> While you're at it, get the Danish proposal voted down as well.

Which was that? Digraphs?

|>
|> [Just in case anyone wants to get picky, this message is generated by me
|> personally, and has no connection with IXI Limited, SCO Corporation,
|> ISO/IEC/JTC1/SC22/WG14, BSI IST/5/-/14, or any other body.]
|>
|> --
|> Clive D.W. Feather     | IXI Ltd (an SCO company) | If you lie to the compiler,
|> clive@x.co.uk          | Vision Park              | it will get its revenge.
|> Phone: +44 223 236 555 | Cambridge   CB4 4ZR      |   - Henry Spencer
|> Fax:   +44 223 236 466 | United Kingdom           |

--
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com




Author: clive@x.co.uk (Clive Feather)
Date: Fri, 6 Aug 1993 08:53:50 GMT
Raw View
In article <CBAM3H.JCG@crdnns.crd.ge.com> volpe@ausable.crd.ge.com writes:
>In article <CBAEH1.3Jr@x.co.uk>, clive@x.co.uk (Clive Feather) writes:
>> Here is a hypothetical implementation that obeys the standard and the
>> interpretation:
> [scenario and examples deleted]
> This is all fine and dandy. But my main point is that if the committee
> mandated that the struct hack *work*, but still allowed bounds info
> to be carried along purely for warning purposes, we'd have the best of
> both worlds and everyone would be happy. Is there any reason why this
> isn't so?

The WG14 committee believe that a reading of the standard is, at least,
better compatible with the "described object view" than with the
"largest object view". At the time of the last meeting, I was neutral on
the subject, but I am coming round to their view.

For example, consider:

    int a [5][5];

    struct fred
    {
        double d;
        int i1 [10];
        int i2 [10];
    }
    f, *pf;
    pf = malloc (sizeof f + 10 * sizeof (int));

Do you believe a [1][7] should be a legal expression ?
Do you believe f.i1 [15] should be a legal expression ?
Do you believe f.i2 [15] should be a legal expression ?
Do you believe *pf->i1 [15] should be a legal expression ?
Do you believe *pf->i2 [15] should be a legal expression ?

If the answer to all of these is "no", you agree with the committee.
If the answer to all of these is "yes", you believe in "largest object view".
If not all your answers are the same, why ?

--
Clive D.W. Feather     | IXI Ltd (an SCO company) | If you lie to the compiler,
clive@x.co.uk          | Vision Park              | it will get its revenge.
Phone: +44 223 236 555 | Cambridge   CB4 4ZR      |   - Henry Spencer
Fax:   +44 223 236 466 | United Kingdom           |




Author: clive@x.co.uk (Clive Feather)
Date: Fri, 6 Aug 1993 09:06:34 GMT
Raw View
In article <CBAMH3.JtD@crdnns.crd.ge.com> volpe@ausable.crd.ge.com writes:
>In article <CBAErp.3M1@x.co.uk>, clive@x.co.uk (Clive Feather) writes:
>> In article <CB8LJn.Ju4@crdnns.crd.ge.com> volpe@ausable.crd.ge.com writes:
>>> Is there a procedure for getting an interpretation ruling repealed?
>> Persuade your national member body, whoever that may be, to vote against
> I assume you mean ANSI?

If you live and work in the USA, then yes. My national member body is
BSI. Jutta's is DIN. Etc.

>> the Record of Response when it is placed in front of ISO/IEC/JTC1/SC22
>> (it hasn't been yet, so it isn't an official response yet). You will need
> Hmmm. What actually has happened so far then if the ruling is not official?
> What's the process? Who issued the ruling originally, if not the final
> authority?

A "Record of Response" is generated by WG14, and passed to SC22. If SC22
accept it (which they would normally do), they send it out to a ballot
of member bodies. Each body votes "Yes", "No, and the following change
would change our vote to Yes", or "Abstain". Failure to vote is treated
as "Yes". If there are no significant No votes, or changes can fix the
No votes without, in the opinion of SC22, invalidating the Yes votes,
the RoR becomes official ISO policy.

Note that an RoR is *not* a Technical Corrigendum, and does not alter
the Standard. If a future Defect Report shows the RoR to contradict the
Standard, the latter takes precedence, and a new RoR will correct the old.

>> While you're at it, get the Danish proposal voted down as well.
> Which was that? Digraphs?

Yes, plus <iso646.h>. For those who haven't seen it before, the current
version (and there have been several) is:

1) Add a new required header <iso646.h> with the following contents:

    #define and    &&
    #define and_eq &=
    #define bitand &
    #define or     ??!??!
    #define or_eq  ??!=
    #define bitor  ??!
    #define compl  ??-
    #define not_eq !=
    #define not    !
    #define xor    ??'
    #define xor_eq ??'=

2) Add the following as alternate spellings of various tokens:

    New    Old   Old (using trigraphs)
    ----------------
    <:     [     ??(
    :>     ]     ??)
    <%     {     ??<
    %>     }     ??>
    %:     #     ??=
    %:%:   ##    ??=??=

The spelling of a token does not affect its meaning (so [ can be
balanced by :> ).

Note that this proposal adds *no* new functionality to the language. It
is also incompatible with similar, but not identical, changes being
proposed to C++. Furthermore, it is incomplete (it doesn't handle "[",
which remains different to "<:", and it doesn't handle \), yet it is
overcomplete (who needs "not" ?).

--
Clive D.W. Feather     | IXI Ltd (an SCO company) | If you lie to the compiler,
clive@x.co.uk          | Vision Park              | it will get its revenge.
Phone: +44 223 236 555 | Cambridge   CB4 4ZR      |   - Henry Spencer
Fax:   +44 223 236 466 | United Kingdom           |




Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Fri, 6 Aug 1993 13:44:17 GMT
Raw View
In article <CBBy1r.Bz6@x.co.uk>, clive@x.co.uk (Clive Feather) writes:
|> In article <CBAM3H.JCG@crdnns.crd.ge.com> volpe@ausable.crd.ge.com writes:
|> >In article <CBAEH1.3Jr@x.co.uk>, clive@x.co.uk (Clive Feather) writes:
|> >> Here is a hypothetical implementation that obeys the standard and the
|> >> interpretation:
|> > [scenario and examples deleted]
|> > This is all fine and dandy. But my main point is that if the committee
|> > mandated that the struct hack *work*, but still allowed bounds info
|> > to be carried along purely for warning purposes, we'd have the best of
|> > both worlds and everyone would be happy. Is there any reason why this
|> > isn't so?
|>
|> The WG14 committee believe that a reading of the standard is, at least,
|> better compatible with the "described object view" than with the

I understand that this is a reasonable opinion, but it doesn't answer my
question above.

|> "largest object view". At the time of the last meeting, I was neutral on
|> the subject, but I am coming round to their view.
|>
|> For example, consider:
|>
|>     int a [5][5];
|>
|>     struct fred
|>     {
|>         double d;
|>         int i1 [10];
|>         int i2 [10];
|>     }
|>     f, *pf;
|>     pf = malloc (sizeof f + 10 * sizeof (int));
|> Do you believe a [1][7] should be a legal expression ?

Yes. It's ugly, and it's bad style, but there's no reason why it *can't* work.
And therefore it *should* work (even if for no other reason than to be
consistent with the struct hack)

|> Do you believe f.i1 [15] should be a legal expression ?

Yes. And the subsequent contents of any of the first five members of
f.i2 should be indeterminate. But I'm willing to accept "no" on the
basis that leaving other members indeterminate is a "bad thing".

|> Do you believe f.i2 [15] should be a legal expression ?

No, because it extends beyond the storage owned by the object f. There's no
telling where this might attempt to write. It could clobber pf, or something
else, on any reasonable implementation.

|> Do you believe *pf->i1 [15] should be a legal expression ?

Syntactically incorrect. You're doing too much dereferencing here. I'll
assume here (and below) that you mean either "pf->i1[15]" or "(*pf).i1[15]".
The answer then is yes, for the same reasons, and with the same restrictions,
as the answer to the second question.

|> Do you believe *pf->i2 [15] should be a legal expression ?

Yes. This is essentially the definition of the struct hack.


|>
|> If the answer to all of these is "no", you agree with the committee
|> If the answer to all of these is "yes", you believe in "largest object view".
|> If not all your answers are the same, why ?

I have given reasons for each individual answer and I think all my answers
(despite the fact that there is one definite "no" answer) are completely
consistent with the largest object view. Granted, doing #1, #2, and #4
may be silly. But the language should not prevent one from doing silly
things if it must also prevent one from doing clever things (#5).
[Paraphrased from Doug Gwyn's comment about Unix.]

|>
|> --
|> Clive D.W. Feather     | IXI Ltd (an SCO company) | If you lie to the compiler,
|> clive@x.co.uk          | Vision Park              | it will get its revenge.
|> Phone: +44 223 236 555 | Cambridge   CB4 4ZR      |   - Henry Spencer
|> Fax:   +44 223 236 466 | United Kingdom           |

--
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com




Author: davisonj@bnr.ca (John M Davison)
Date: 3 Aug 1993 18:51:06 GMT
Raw View
        Note: Since this fprintf issue is common to both C and C++, I have
decided to go ahead and cross-post this article to comp.std.c++.  For those who
have just gotten in on this thread, I previously asked if ANSI X3.159-1989,
Section 4.9.6.1, Page 135, Lines 1-2 restricts the "%p" specifier to accept
only "void *", or if various qualifications (e.g. const, volatile) are
allowed.  This thread started because I would like to cast to (const void *)
instead of (void *) in my printf calls in order to minimize the number of
"const cast-aways" that I commit in a C program, but I am not sure if ANSI
X3.159-1989 allows this with defined results.

        In article <23luro$io5@news.cs.tu-berlin.de> jutta@cs.tu-berlin.de
(Jutta Degener) writes:
>diamond@jit.dec.com (Norman Diamond) writes:
...
>> This doesn't have to work.  The implementation's representation of a
>> pointer to const void doesn't have to be the same as the implementation's
>> representation of a pointer to plain void.
>
>Has too.   From ANSI section 3.1.2.5, Types:...

        So, then, do qualifications make a difference in a call to printf using
the "%p" flag character?  How about the other flag characters?

        Since the representations are identical regardless of qualifications,
it would seem that this boils down to the question of whether or not printf has
the right to make use of the fact that the data being pointed to are not
const-qualified (or volatile, for that matter).  (I can't see anything good
coming out of printf having the right to do this, but it doesn't appear that
the standard takes a stand on this either way.)

        Is a request for clarification in order here?
--
John Davison, davisonj@ecn.purdue.edu <---- send followups to THIS ADDRESS!!!!!
(Otherwise your mail will bounce!)  If you work at NT/BNR, please COCOS to
"John Davison".  The information contained in this article isn't necessarily
representative of Northern Telecom or BNR.




Author: diamond@jit.dec.com (Norman Diamond)
Date: 4 Aug 1993 06:36:30 GMT
Raw View
Responses here to three articles.

In article <CB6H2y.EHn@dcs.ed.ac.uk> ddr@dcs.ed.ac.uk (Douglas Rogers) writes:
>In article <23kf2a$r3o@usenet.pa.dec.com>, diamond@jit.dec.com (Norman Diamond) writes:
>>In article <23jjnb$b9e@crchh327.bnr.ca> jackw@bnr.ca (John Davison in care of Jack Wasserman) writes:
>>>const void *
>>>const void * const

>>All of these are the same as (void const *).  The order of the specifiers
>>void and const doesn't matter, and a const at the highest level has no effect.

>OK, I know there are differences in passing variables rather than casting, but
>how does this tie in with teh standard library function qsort which requires a
>pointer to a function of type:-
>typedef int compar_t(const void *, const void *);

The two issues do not really tie in except a bit by coincidence.

Since printf() is a varargs function and only the first parameter has its
type declared in the prototype, only the first parameter will automatically
be cast to type (const char *) [if such conversion is necessary and is
allowed to happen automatically].  Other arguments will be subject to default
promotions such as short to int and float to double, but will not otherwise
be converted.  This is why mismatched types and format specifications are bad.

All parameters of qsort() have their types declared in the prototype.
Each argument will be cast automatically [if necessary and allowed] to the
corresponding parameter type.  However, conversion of one type of function
pointer to another type of function pointer does not happen automatically.
You can write a cast yourself if you want, and cause your call to qsort()
to evade one type check, but qsort() itself will not cast its parameter
back to the actual type of your comparison function before calling your
comparison function.  So if your comparison function doesn't actually have
the correct type, it will [probably] crash.


In article <23luro$io5@news.cs.tu-berlin.de> jutta@cs.tu-berlin.de (Jutta Degener) writes:
>diamond@jit.dec.com (Norman Diamond) writes:
>> In article <...> jackw@bnr.ca (John Davison in care of Jack Wasserman) writes:
>>> void const *

>> This doesn't have to work.  The implementation's representation of a
>> pointer to const void doesn't have to be the same as the implementation's
>> representation of a pointer to plain void.

>Has too.   From ANSI section 3.1.2.5, Types:
># Similarly, pointers to qualified or unqualified versions of
># compatible types shall have the same representation and
># alignment requirements.[16]

Hmmmmmmmmmmmm.  I almost want to ask myself angrily how I could forget that,
but in fact I know why I forgot.

The committee recently issued an interpretation ruling that pointer to int
and pointer to int do not have to have the same representation.  Int and
int are compatible because their types are the same, so pointer to int and
pointer to int are pointers to compatible types, but if one is pointing to
the first element of an array of 5 ints and one is pointing to the first
element of an array of 10 ints then their representations do not have to
be the same.

I give up.


In article <23mc2q$ie0@crchh327.bnr.ca> davisonj@bnr.ca (John M Davison) writes:
>        Note: Since this fprintf issue is common to both C and C++, I have
>decided to go ahead and cross-post this article to comp.std.c++.

I've honoured your cross-post, though I'm not sure if they want to be
bothered by an issue that is identical in the two languages.  (But if
that's the case, someone will flame us gently, right? :-)

>        So, then, do qualifications make a difference in a call to printf using
>the "%p" flag character?  How about the other flag characters?

For any format specifier or flag that corresponds to a numeric value (such
as %d or %f or %c, or the * length flag), there are no qualifications.
Numeric values are not lvalues.

For almost any format specifier that corresponds to a pointer value (such
as %s), the question of whether the pointer can address a qualified type
is the same as for %p.  But if %n corresponds to a pointer to const integer
then you'll be in trouble :-)

(Hey, anyone know which integer type has to be pointed to by %n's argument?)

>        Since the representations are identical regardless of qualifications,
>it would seem that this boils down to the question of whether or not printf has
>the right to make use of the fact that the data being pointed to are not
>const-qualified (or volatile, for that matter).  (I can't see anything good
>coming out of printf having the right to do this, but it doesn't appear that
>the standard takes a stand on this either way.)

%p formats the output in an implementation-defined manner.  An implementation
could choose to decode some of the bits of a pointer value for us, and tell
us in Japanese that the pointer's type is pointer to const something-or-other,
though it happens to actually point to a non-const object at the moment.

>        Is a request for clarification in order here?

Yeah I'd say so, but I'm not sure if further answers will clarify it :-(
--
 <<  If this were the company's opinion, I would not be allowed to post it.  >>
A program in conformance will not tend to stay in conformance, because even if
it doesn't change, the standard will.       Force = program size * destruction.
Every technical corrigendum is met by an equally troublesome new defect report.




Author: clive@x.co.uk (Clive Feather)
Date: Wed, 4 Aug 1993 11:07:23 GMT
Raw View
In article <23nlde$25q@usenet.pa.dec.com> diamond@jit.dec.com (Norman Diamond) writes:
>In article <23luro$io5@news.cs.tu-berlin.de> jutta@cs.tu-berlin.de (Jutta Degener) writes:
>>diamond@jit.dec.com (Norman Diamond) writes:
>>> This doesn't have to work.  The implementation's representation of a
>>> pointer to const void doesn't have to be the same as the implementation's
>>> representation of a pointer to plain void.
>> Has too.   From ANSI section 3.1.2.5, Types:
>> # Similarly, pointers to qualified or unqualified versions of
>> # compatible types shall have the same representation and
>> # alignment requirements.[16]
> Hmmmmmmmmmmmm.  I almost want to ask myself angrily how I could forget that,
> but in fact I know why I forgot.
>
> The committee recently issued an interpretation ruling that pointer to int
> and pointer to int do not have to have the same representation.  Int and
> int are compatible because their types are the same, so pointer to int and
> pointer to int are pointers to compatible types, but if one is pointing to
> the first element of an array of 5 ints and one is pointing to the first
> element of an array of 10 ints then their representations do not have to
> be the same.

I'm not aware of any such ruling. What they said is that a pointer can
carry bounds information around with it, and that assigning such a
pointer can assign the bounds information as well. They also said that
the bounds can be somewhat tighter than some people think (see the
struct hack thread). However, there is only one type "pointer to int",
and while "pointer to const int" isn't the same, they must have the same
representation and alignment requirements.

--
Clive D.W. Feather     | IXI Ltd (an SCO company) | If you lie to the compiler,
clive@x.co.uk          | Vision Park              | it will get its revenge.
Phone: +44 223 236 555 | Cambridge   CB4 4ZR      |   - Henry Spencer
Fax:   +44 223 236 466 | United Kingdom           |




Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Wed, 4 Aug 1993 13:30:59 GMT
Raw View
In article <23nlde$25q@usenet.pa.dec.com>, diamond@jit.dec.com (Norman Diamond) writes:
|>
|> >> This doesn't have to work.  The implementation's representation of a
|> >> pointer to const void doesn't have to be the same as the implementation's
|> >> representation of a pointer to plain void.
|>
|> >Has too.   From ANSI section 3.1.2.5, Types:
|> ># Similarly, pointers to qualified or unqualified versions of
|> ># compatible types shall have the same representation and
|> ># alignment requirements.[16]
|>
|> Hmmmmmmmmmmmm.  I almost want to ask myself angrily how I could forget that,
|> but in fact I know why I forgot.
|>
|> The committee recently issued an interpretation ruling that pointer to int
                                                               ^^^^^^^^^^^^^^
|> and pointer to int do not have to have the same representation.  Int and
       ^^^^^^^^^^^^^^

At first I thought you made a typo (leaving out "const" before one of the
ints) and I was going to make a wiseass remark about dropping C
altogether, until I read the rest of the paragraph and realized that
you drew this correct conclusion from the Struct Hack interpretation
ruling.

The Committee is on drugs. :-(

|> int are compatible because their types are the same, so pointer to int and
|> pointer to int are pointers to compatible types, but if one is pointing to
|> the first element of an array of 5 ints and one is pointing to the first
|> element of an array of 10 ints then their representations do not have to
|> be the same.
|>
|> I give up.

You and me both. (Now where'd I put that Fortran compiler...)


|> >        Since the representations are identical regardless of qualifications,
|> >it would seem that this boils down to the question of whether or not printf has
|> >the right to make use of the fact that the data being pointed to are not
|> >const-qualified (or volatile, for that matter).  (I can't see anything good
|> >coming out of printf having the right to do this, but it doesn't appear that
|> >the standard takes a stand on this either way.)
|>
|> %p formats the output in an implementation-defined manner.  An implementation
|> could choose to decode some of the bits of a pointer value for us, and tell
|> us in Japanese that the pointer's type is pointer to const something-or-other,
|> though it happens to actually point to a non-const object at the moment.

How could any of the bits indicate that it is a pointer to CONST
something-or-other. Have you *again* forgotten 3.1.2.5 so soon?

|>
|> >        Is a request for clarification in order here?
|>
|> Yeah I'd say so, but I'm not sure if further answers will clarify it :-(

Is there a procedure for getting an interpretation ruling repealed?

--
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com




Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Wed, 4 Aug 1993 13:40:33 GMT
Raw View
In article <CB8EwB.GAw@x.co.uk>, clive@x.co.uk (Clive Feather) writes:
|> In article <23nlde$25q@usenet.pa.dec.com> diamond@jit.dec.com (Norman Diamond) writes:
|> >In article <23luro$io5@news.cs.tu-berlin.de> jutta@cs.tu-berlin.de (Jutta Degener) writes:
|> >>diamond@jit.dec.com (Norman Diamond) writes:
|> >>> This doesn't have to work.  The implementation's representation of a
|> >>> pointer to const void doesn't have to be the same as the implementation's
|> >>> representation of a pointer to plain void.
|> >> Has too.   From ANSI section 3.1.2.5, Types:
|> >> # Similarly, pointers to qualified or unqualified versions of
|> >> # compatible types shall have the same representation and
|> >> # alignment requirements.[16]
|> > Hmmmmmmmmmmmm.  I almost want to ask myself angrily how I could forget that,
|> > but in fact I know why I forgot.
|> >
|> > The committee recently issued an interpretation ruling that pointer to int
|> > and pointer to int do not have to have the same representation.  Int and
|> > int are compatible because their types are the same, so pointer to int and
|> > pointer to int are pointers to compatible types, but if one is pointing to
|> > the first element of an array of 5 ints and one is pointing to the first
|> > element of an array of 10 ints then their representations do not have to
|> > be the same.
|>
|> I'm not aware of any such ruling. What they said is that a pointer can
|> carry bounds information around with it, and that assigning such a
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Thus the "bounds information" is part of the representation, by definition.

|> pointer can assign the bounds information as well. They also said that
|> the bounds can be somewhat tighter than some people think (see the
|> struct hack thread). However, there is only one type "pointer to int",

int a[3];
int b[5];
There USED TO be only one type "pointer to int", but now the committee
has ruled that the pointer-to-int "a" is different from the pointer-to-int
"b".

|> and while "pointer to const int" isn't the same, they must have the same
|> representation and alignment requirements.

Yes, the Standard guarantees that, but the committee has negated that.
The standard also guarantees that "pointer-to-void" has the same
rep and alignment as "pointer-to-char", but the committee has interpreted
this to mean that they don't have to have the same representation,
particularly if the pointer-to-char's representation includes bits that
indicate that it points to the first element of an array of 3 chars.

|>
|> --
|> Clive D.W. Feather     | IXI Ltd (an SCO company) | If you lie to the compiler,
|> clive@x.co.uk          | Vision Park              | it will get its revenge.
|> Phone: +44 223 236 555 | Cambridge   CB4 4ZR      |   - Henry Spencer
|> Fax:   +44 223 236 466 | United Kingdom           |

--
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com




Author: daniels@NeoSoft.com (Brad Daniels)
Date: Wed, 4 Aug 1993 16:39:10 GMT
Raw View
In article <CB8LzL.KBH@crdnns.crd.ge.com> volpe@ausable.crd.ge.com writes:
>In article <CB8EwB.GAw@x.co.uk>, clive@x.co.uk (Clive Feather) writes:
>|> In article <23nlde$25q@usenet.pa.dec.com> diamond@jit.dec.com (Norman Diamond) writes:
>|> > The committee recently issued an interpretation ruling that pointer to int
>|> > and pointer to int do not have to have the same representation.  Int and
>|> > int are compatible because their types are the same, so pointer to int and
>|> > pointer to int are pointers to compatible types, but if one is pointing to
>|> > the first element of an array of 5 ints and one is pointing to the first
>|> > element of an array of 10 ints then their representations do not have to
>|> > be the same.
>|>
>|> I'm not aware of any such ruling. What they said is that a pointer can
>|> carry bounds information around with it, and that assigning such a
>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>Thus the "bounds information" is part of the representation, by definition.
>
>|> pointer can assign the bounds information as well. They also said that
>|> the bounds can be somewhat tighter than some people think (see the
>|> struct hack thread). However, there is only one type "pointer to int",
>
>int a[3];
>int b[5];
>There USED TO be only one type "pointer to int", but now the committee
>has ruled that the pointer-to-int "a" is different from the pointer-to-int
>"b".

No.  Both quantities are represented as "location in memory plus bounds
information."  The *contents* of the bounds information may differ, but
the *representation* is identical.  Thus, all integer pointer types still
must have the same representation, but that representation may carry new
information.  I haven't seen the exact wording of the ruling in question,
but your interpretation seems a little off the mark...  I like the idea
of including optional bounds information with integer pointers, as long
as all integer pointers use the same representation.

Think about it:  An "int *" would have to be able to contain either "a"
or "b" in your example.  That means any object placed in an "int *" may
include bounds information which must be preserved.  Such preservation can
only happen if the "int *" representation is the same as any array address
representation.  No conversion needs to occur to preserve the information,
and the bits can be copied intact.  A sufficiently clever compiler can
even guarantee that all integer pointers have *meaningful* bounds information,
even when generated using malloc.  A C++ compiler using such an approach
can do even better with new [].  Pointers with array bounds information could
eliminate problems of delete vs. delete[].

This ruling sounds to me like one of the best additions to the language yet,
since it allows very useful changes without requiring them, and enable a con-
forming compiler to prevent illegal accesses in most programs.  Of course,
some system programs may legitimately need unadorned address values, but
such code tends to be architecture-dependent anyway, and casts to int or long
can provide values with unknown bounds...  If such a value were cast back
to a pointer, the pointer value would similarly have to reflect the unknown
nature of the array bounds.

I think I'm starting to repeat myself, so I'll stop now.  I find this whole
concept very exciting, and hope to see it as an option on compilers in the
future.

- Brad
--
Brad Daniels   |  "Let others praise ancient times.
daniels@neosoft.com  |   I am glad I was born in these."
I don't work for NeoSoft, and | - Ovid (43 B.C. - 17 A.D)
don't speak for my employer. |




Author: warwick@cs.uq.oz.au (Warwick Allison)
Date: 4 Aug 93 23:38:36 GMT
Raw View
In <23mc2q$ie0@crchh327.bnr.ca> davisonj@bnr.ca (John M Davison) writes:

>        Note: Since this fprintf issue is common to both C and C++, I have
>decided to go ahead and cross-post this article to comp.std.c++.

stdio is a standard C library.  The C++ comparable is iostream,
which does, however, have:

    ostream& operator<<(void *p);

>This thread started because I would like to cast to (const void *)
>instead of (void *) in my printf calls in order to minimize the number of
>"const cast-aways" that I commit in a C program...

which could be a similar problem.  There is no semantic difference
between (void *p) and (const void *p), since "void" is conceptually a
size-zero object - and therefore there is nothing to modify!

--
Warwick
  _-_|\      warwick@cs.uq.oz.au            /
 /     * <-- Computer Science Department,  /
 \_.-._/     University of Queensland,    /         How now, Tao cow?
      v      Brisbane, Australia.        /




Author: clive@x.co.uk (Clive Feather)
Date: Thu, 5 Aug 1993 12:53:25 GMT
Raw View
In article <CB8LzL.KBH@crdnns.crd.ge.com> volpe@ausable.crd.ge.com writes:
>In article <CB8EwB.GAw@x.co.uk>, clive@x.co.uk (Clive Feather) writes:
>> In article <23nlde$25q@usenet.pa.dec.com> diamond@jit.dec.com (Norman Diamond) writes:
>>> The committee recently issued an interpretation ruling that pointer to int
>>> and pointer to int do not have to have the same representation.  Int and
>>> int are compatible because their types are the same, so pointer to int and
>>> pointer to int are pointers to compatible types, but if one is pointing to
>>> the first element of an array of 5 ints and one is pointing to the first
>>> element of an array of 10 ints then their representations do not have to
>>> be the same.
>> I'm not aware of any such ruling. What they said is that a pointer can
>> carry bounds information around with it, and that assigning such a
>Thus the "bounds information" is part of the representation, by definition.

I'll repeat what someone else has said: the bounds information is part
of the *value* of the pointer, not the representation - using your
argument, no two pointers can have the same type if they point to two
different objects. This is clearly ridiculous.

> int a[3];
> int b[5];
> There USED TO be only one type "pointer to int", but now the committee
> has ruled that the pointer-to-int "a" is different from the pointer-to-int
> "b".

No they haven't.

> The standard also guarantees that "pointer-to-void" has the same
> rep and alignment as "pointer-to-char", but the committee has interpreted
> this to mean that they don't have to have the same representation,
> particularly if the pointer-to-char's representation includes bits that
> indicate that it points to the first element of an array of 3 chars.

Here is a hypothetical implementation that obeys the standard and the
interpretation:

- The machine has 64 kilobytes of memory, with 8 bit bytes.
- All pointers are 6 bytes.
- All pointers use the same representation.
- A pointer retains the information:
  * address of first element of the array object pointed to
  * number of bytes in the array object pointed to
  * byte offset of the element of the array object pointed to
  (each of these is two bytes)

Any pointer can be assigned to any other pointer and back again, without
losing information, though using a pointer to the wrong type might yield
an alignment error.

    int a;      /* Suppose a has address 0x1234, and ints are 4 bytes */
    int b [4];  /* Suppose b [0] has address 0x5678 */
    int *p;
    void *v;
    char *c;

    p = &a;     /* p now holds (0x1234,  4, 0x1234) */
    p = b + 2;  /* p now holds (0x5678, 16, 0x5680) */
    p++;        /* p now holds (0x5678, 16, 0x5684) */
    v = p;      /* v now holds (0x5678, 16, 0x5684) */
    c = v;      /* c now holds (0x5678, 16, 0x5684) */
    c++;        /* c now holds (0x5678, 16, 0x5685) */
    p++;        /* p now holds (0x5678, 16, 0x5688)
                   Attempts to use *p will cause a bounds error */
    p++;        /* p attempts to hold (0x5678, 16, 0x568C) - bounds error */
    p = &a + 1; /* p now holds (0x1234,  4, 0x1238)
                   Attempts to use *p will cause a bounds error */

--
Clive D.W. Feather     | IXI Ltd (an SCO company) | If you lie to the compiler,
clive@x.co.uk          | Vision Park              | it will get its revenge.
Phone: +44 223 236 555 | Cambridge   CB4 4ZR      |   - Henry Spencer
Fax:   +44 223 236 466 | United Kingdom           |




Author: clive@x.co.uk (Clive Feather)
Date: Thu, 5 Aug 1993 12:59:48 GMT
Raw View
In article <CB8LJn.Ju4@crdnns.crd.ge.com> volpe@ausable.crd.ge.com writes:
> The Committee is on drugs. :-(

This is libelous. You might not agree with the interpretation, but that
is no reason to be insulting.

> Is there a procedure for getting an interpretation ruling repealed?

Persuade your national member body, whoever that may be, to vote against
the Record of Response when it is placed in front of ISO/IEC/JTC1/SC22
(it hasn't been yet, so it isn't an official response yet). You will need
to get at least two, and preferably three, NO votes, so you will need to
get several member bodies involved.

While you're at it, get the Danish proposal voted down as well.

[Just in case anyone wants to get picky, this message is generated by me
personally, and has no connection with IXI Limited, SCO Corporation,
ISO/IEC/JTC1/SC22/WG14, BSI IST/5/-/14, or any other body.]

--
Clive D.W. Feather     | IXI Ltd (an SCO company) | If you lie to the compiler,
clive@x.co.uk          | Vision Park              | it will get its revenge.
Phone: +44 223 236 555 | Cambridge   CB4 4ZR      |   - Henry Spencer
Fax:   +44 223 236 466 | United Kingdom           |




Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Thu, 5 Aug 1993 13:23:54 GMT
Raw View
In article <CB8u9E.J10@sugar.NeoSoft.COM>, daniels@NeoSoft.com (Brad Daniels) writes:
|> In article <CB8LzL.KBH@crdnns.crd.ge.com> volpe@ausable.crd.ge.com writes:
|> >
|> >int a[3];
|> >int b[5];
|> >There USED TO be only one type "pointer to int", but now the committee
|> >has ruled that the pointer-to-int "a" is different from the pointer-to-int
|> >"b".
|>
|> No.  Both quantities are represented as "location in memory plus bounds
|> information."  The *contents* of the bounds information may differ, but
|> the *representation* is identical.

Ok, I'll concede that point.


|> This ruling sounds to me like one of the best additions to the language yet,
|> since it allows very useful changes without requiring them, and enable a con-
|> forming compiler to prevent illegal accesses in most programs.  Of course,

The ruling is useless because it doesn't allow anything that a compiler
couldn't otherwise do. There was never anything that said an implementation
*couldn't* keep track of pointer bounds and such, as long as it only
issued *warnings* instead of causing undefined behavior. The benefits of
extra bounds checking could still be obtained in a conforming implementation
*without* ruling that the struct hack is illegal.

|> --
|> Brad Daniels   |  "Let others praise ancient times.
|> daniels@neosoft.com  |   I am glad I was born in these."
|> I don't work for NeoSoft, and | - Ovid (43 B.C. - 17 A.D)
|> don't speak for my employer. |

--
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com




Author: volpe@bart.crd.ge.com (Christopher R. Volpe)
Date: Thu, 5 Aug 1993 15:38:05 GMT
Raw View
In article <CBAEH1.3Jr@x.co.uk>, clive@x.co.uk (Clive Feather) writes:
|> In article <CB8LzL.KBH@crdnns.crd.ge.com> volpe@ausable.crd.ge.com writes:

|> >Thus the "bounds information" is part of the representation, by definition.
|>
|> I'll repeat what someone else has said: the bounds information is part
|> of the *value* of the pointer, not the representation - using your
|> argument, no two pointers can have the same type if they point to two
|> different objects. This is clearly ridiculous.

I conceded this point in another post. But this point is not central
to my argument.

|> Here is a hypothetical implementation that obeys the standard and the
|> interpretation:
[scenario and examples deleted]

This is all fine and dandy. But my main point is that if the committee
mandated that the struct hack *work*, but still allowed bounds info
to be carried along purely for warning purposes, we'd have the best of
both worlds and everyone would be happy. Is there any reason why this
isn't so?

|> --
|> Clive D.W. Feather     | IXI Ltd (an SCO company) | If you lie to the compiler,
|> clive@x.co.uk          | Vision Park              | it will get its revenge.
|> Phone: +44 223 236 555 | Cambridge   CB4 4ZR      |   - Henry Spencer
|> Fax:   +44 223 236 466 | United Kingdom           |

--
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com