doubtful assumptions about pointers

bdm659 at csc.anu.oz bdm659 at csc.anu.oz
Thu Jan 11 00:05:59 AEST 1990


This is an article about the semantics of pointers as defined by the
ANSI standard for C (henceforth pANS).  It is not necessarily about any
existing C compiler, nor about C as defined by any source other than pANS.
You probably can't contribute to it significantly unless you have a copy of
pANS. If you think that any of my claims are wrong (perfectly possible) then
the only way to demonstrate that is via precise reference to the text of pANS.

Any quotes from pANS refer to the version of Dec. 7, 1988.  Note that some
relevant wording changed a lot in the last few revisions.

I will call a pointer "valid" if it can be made by a strictly conforming
program.  There appear to be three kinds of valid pointers:
P1: pointers to objects
P2: null pointers
P3: pointers to "just past" an object (especially array objects, but any
    pointer to an object can be regarded as a pointer to an array of size
    one, then incremented once).

The following is a list of Doubtful Assumptions (DAs).  The definition of
a DA is "an assumption that a C programmer might be tempted to make, but
which I cannot prove to be justified according to pANS".  Determining
whether something follows from pANS is not always a simple matter, so some
of my DAs might turn out to be not doubtful at all.  In fact, I hope I'm
wrong about some of them.  I'd welcome proofs in either case.

DA[0]:  int *pi; char *pc;
        Suppose pi is valid, and do  pc = (char*) pi.  Then *pc overlaps *pi
        in the sense that changing the value of *pc changes the value of *pi.

DA[1]:  int *pi, *pj;  char *pc, *pd;
        Suppose pi and pj are valid,  and that  pi == pj .
        Now do  pc = (char*) pi; pd = (char*) pj .
        Then  pc == pd .
        [I bet this one generates some heat.  Don't forget to justify
         your disproof with references to pANS.]

DA[2]:  Just like DA[1], but using type void* instead of char*.

DA[3]:  long *pi, *pj;
        Suppose that pi is valid, and do  pj = (long*)(int*) pi;
        Then  pi == pj .
        [comment: there's no rule that says an int can't have a more
         strict alignment requirement that a long.]

DA[4]:  int i, *pi;
        Suppose pi is a null pointer, and do  i = (int) pi .
        Then  i == 0 .

DA[5]:  Just like DA[4], but with i of type  unsigned long .

DA[6]:  int *pi, *pj;
        Suppose pi is valid, and do  pj = (int*)(unsigned long) pi.
        Then  pi == pj .

DA[7]:  int i, *pi;
        Suppose i != 0, and do  pi = (int*) i .
        Then  pi != (int*)0 .

DA[8]:  int *pi, *pj;
        Suppose pi is a valid pointer of kind P3, and do
        pj = (int*)(char*) pi .   Then  pi == pj .
        [comment: the rule in section 3.3.4 only applies to pointers
         to objects, which pi might not be.]

DA[9]:  int *pi;
        Suppose that an external function f() is declared without prototype.
        It expects a single argument of type void*.   Assume that pi is valid.
        Then the call  f(pi)  works.
        [comment:  See my remarks on section 3.1.2.5 below.]

DA[10]: void *pv;  external void *f();
        In fact, f returns a value of type int*.
        Then   pv = f()  works.
        [comment:  See my remarks on section 3.1.2.5 below.]

References and some nit-picking.

1.6.      definitions of "object" and "alignment"
3.1.2.5.  types and type terminology
          definitions of "object type" and "incomplete type"
   nit-pick:  This section several rules of the form "types X and Y have the
              same representation and alignment requirements".  Footnote 15
              tells us that this is intended to imply interchangeability as
              function arguments, function return values, and members of
              unions.  However, this does not follow from the rule.
              Interchangeability of two types as function arguments requires,
              in addition, equality of argument-passing mechanisms.  This is
              nowhere prescribed.
3.2.2.3.  conversions amongst pointer types, null pointers
3.3.2.1.  array subscripting
3.3.3.2.  * and & operators
3.3.4.    more on conversion amongst pointer types
          conversions between integral types and pointers
   nit-pick:  The case of (obj*)0 should be excluded from these rules
              as it is specified differently in 3.2.2.3.
3.3.6.    pointer + integer, pointers just past an object
3.3.8.    relational operators
   nit-pick:  The phrase "or both are null pointers" is missing from the
              sentence in lines 8-10.  See the otherwise identical sentence
              in section 3.3.9.
3.3.9.    equality operators
3.3.16.1. simple assignment
3.5.2.1.  conversions between pointers to union members

===========================================================
Brendan McKay.  bdm at anucsd.oz.au  or  bdm659 at csc1.anu.oz.au
terrorist: n. an individual who behaves like a government  (original)



More information about the Comp.std.c mailing list