home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.lang.c:17031 comp.std.c:3056
- Newsgroups: comp.lang.c,comp.std.c
- Path: sparky!uunet!munnari.oz.au!cs.mu.OZ.AU!munta.cs.mu.OZ.AU!fjh
- From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
- Subject: Struct hack (was: Re: Is this ANSI?)
- Message-ID: <9232902.26984@mulga.cs.mu.OZ.AU>
- Followup-To: comp.std.c
- Sender: news@cs.mu.OZ.AU
- Organization: Computer Science, University of Melbourne, Australia
- References: <9eRguB1w165w@quest.UUCP> <24238@alice.att.com> <1992Nov21.125038.26244@sq.sq.com> <24270@alice.att.com>
- Date: Mon, 23 Nov 1992 15:48:23 GMT
- Lines: 136
-
- ark@alice.att.com (Andrew Koenig) writes:
-
- >... to convince me
- >that it's legal, you'd have to find language in the standard that allows
- >it.
-
- Sure, but to convince me that it's illegal, you'd have to find language
- in the standard that disallows it :-)
-
- >I looked around a little bit, and here is what I found, in the description
- >of pointer+integer:
- >
- > Unless both the pointer operand and the result point to
- > elements of the same array object, or the pointer
- > operand points one past the last element of an array
- > object and the result points to an element of the same
- > array object, the behavior is undefined if the result
- > is used as an operand of the unary * operator.
-
- The way I read it, this sentence is implicitly existentially qualified
- with respect to the array object. That is, it means "Unless there
- exists some array object which is pointed to by both the pointer
- operand and the result, ...". This reading is supported
- by the use of the phrase "the last element of *an* array object".
-
- >Now, let's take a look at the example again:
- [example omitted]
- >At issue is the assignment to p->data[5].
- >
- >As I see it, the question is just what p->data is. If I look at the
- >definition of p, I see that p->data is an array of char with one element.
- >The way I've used it is, of course, equivalent to *(p->data+5).
- >
- >That means p->data is converted to a pointer to its initial element,
- >namely a pointer to the first (and only) element of a one-element array.
- >[Remember this assertion].
-
- This is not the *only* thing that p->data points to.
-
- >So, we take that pointer, add 5 to it,
- >and apply unary * to the result. Well, the pointer operand of +
- >points to an element of the array object, but the result does not;
- >there is only one element and the result doesn't point there.
- >The result of using unary * is therefore undefined.
-
- No, because *there exists* an array object for which
- both the pointer operand and the result point to elements of that
- array object.
-
- >Now, look back at the assertion I asked you to remember. I expect
- >that Mark Brader is going to say `But p->data isn't an array of
- >one element, it's an array of 101 elements. After all, when you
- >said malloc(sizeof(struct FM + 100), you allocated enough memory
- >for 101 elements!'
- >
- >Here are two reasons I disagree:
- >
- > 1. Suppose I said
- >
- > struct FM *q = (struct FM *) malloc(sizeof(struct FM) + 100);
- >
- > and later said
- >
- > *p = *q;
- >
- > Is the compiler obligated to realize that p and q actually point
- > to objects of type other than struct FM? That is, is it obligated
- > to copy all the `extra' elements in the data array?
-
- No; but I don't see how this is directly relevant.
-
- > 2. If you declare p by saying
- >
- > struct FM *p;
- >
- > then I don't think there is any place in the standard that says
- > other than that *p is an lvalue of type FM. Once you acknowledge
- > that *p is of type FM, I don't see how you can get away from the
- > p->data being anything other than a one-element array.
-
- As I see it, the question is not what is the type of p->data, the question is
- rather what does the pointer (char *)p->data point to, and the answer is
- that it points to a one-element array and *also* points into a larger array.
-
- > What I found
- > in the standard that talks about this is:
- >
- > The pointer returned [by malloc or realloc] if the
- > allocation succeeds is suitably aligned so that it
- > may be assigned to a pointer to any type of object
- > and then used to access such an object or an array
- > of such objects in the space allocated (until the
- > space is explicitly freed or reallocated).
- >
- > It doesn't say that it may be assigned to a pointer to some
- > type of object and then used to access an object of some other
- > type.
-
- No, but it doesn't say that this is *not* allowed, either.
-
- >Another way to look at it is this. Suppose I have a compiler that rejects:
- >
- > void f(struct FM *p)
- > {
- > p->data[5] = '?';
- > }
- >
- >on the basis that p->data is a one-element array and you can't refer to
- >the fifth element of a one-element array. What part of the standard can
- >you cite to convince me that my compiler isn't allowed to diagnose this?
- >-- especially after the description of pointer arithmetic above?
-
- As I said before, the fact that p->data is a one-element array doesn't
- imply that (char *)p->data does not also point to some other array which does
- have a element at the position *(p->data+5), and if it does, the
- statement p->data[5] = '?' should be quite legal. Obviously the compiler
- can't reject a program because it *might* contain a statement whose behaviour
- is undefined. (By the way: exactly when *is* a compiler allowed to reject
- a program?)
-
- Clearly the statement is syntactically correct.
- I believe that the onus is on those who believe the statement to be illegal to
- cite supporting evidence, and I do not believe that what you have just
- cited is convincing.
-
- P.S. I haven't read the standard myself and I could well be wrong :-)
- I am just arguing a point of view, to see what the response
- from supporters of the opposing point of view will be.
-
- P.P.S. Followups to comp.std.c.
-
- --
- Fergus Henderson fjh@munta.cs.mu.OZ.AU
- This .signature virus is a self-referential statement that is true - but
- you will only be able to consistently believe it if you copy it to your own
- .signature file!
-