home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!linac!att!att!allegra!alice!ark
- From: ark@alice.att.com (Andrew Koenig)
- Newsgroups: comp.lang.c
- Subject: Re: Is this ANSI?
- Message-ID: <24270@alice.att.com>
- Date: 22 Nov 92 14:32:08 GMT
- Article-I.D.: alice.24270
- References: <9eRguB1w165w@quest.UUCP> <24238@alice.att.com> <1992Nov21.125038.26244@sq.sq.com>
- Reply-To: ark@alice.UUCP ()
- Organization: AT&T Bell Laboratories, Murray Hill NJ
- Lines: 119
-
- In article <1992Nov21.125038.26244@sq.sq.com> msb@sq.sq.com (Mark Brader) writes:
-
- > Andrew, I'm afraid that *you* are definitely wrong, period.
-
- After thinking it over carefully, I'm not convinced.
-
- > The key word here is "allocate", meaning that the intention is to
- > do something like
-
- > struct FM *p = malloc (sizeof (struct FM) + n);
-
- Agreed.
-
- > In this situation the standard *does* allow a correctly declared
- > array element of the struct to be subscripted out of range, as long
- > as you stay within the malloc()ed area. This has been discussed
- > at great length in comp.std.c not too long ago. The only argument
- > that it might be illegal in this situation which was not countered
- > by reference to the standard amounted to saying that they must
- > have *intended* it to be illegal and didn't get the wording right.
-
- Unfortunately, I wasn't in on that discussion. But to convince me
- that it's legal, you'd have to find language in the standard that allows
- 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.
-
- Now, let's take a look at the example again:
-
- struct FM {
- int size;
- char data[1];
- };
-
- main()
- {
- struct FM *p = (struct FM *) malloc(sizeof(struct FM) + 100);
- p->data[5] = '?';
- }
-
- 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]. 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.
-
- 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?
-
- 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. 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. That is, it says that the result of malloc may be
- assigned to a struct FM * and then used to access an object
- of type struct FM. It says nothing about struct FM representing
- a family of related types.
-
- 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?
- --
- --Andrew Koenig
- ark@europa.att.com
-