home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / lang / c / 17008 < prev    next >
Encoding:
Text File  |  1992-11-22  |  4.7 KB  |  132 lines

  1. Path: sparky!uunet!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!linac!att!att!allegra!alice!ark
  2. From: ark@alice.att.com (Andrew Koenig)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: Is this ANSI?
  5. Message-ID: <24270@alice.att.com>
  6. Date: 22 Nov 92 14:32:08 GMT
  7. Article-I.D.: alice.24270
  8. References: <9eRguB1w165w@quest.UUCP> <24238@alice.att.com> <1992Nov21.125038.26244@sq.sq.com>
  9. Reply-To: ark@alice.UUCP ()
  10. Organization: AT&T Bell Laboratories, Murray Hill NJ
  11. Lines: 119
  12.  
  13. In article <1992Nov21.125038.26244@sq.sq.com> msb@sq.sq.com (Mark Brader) writes:
  14.  
  15. > Andrew, I'm afraid that *you* are definitely wrong, period.
  16.  
  17. After thinking it over carefully, I'm not convinced.
  18.  
  19. > The key word here is "allocate", meaning that the intention is to
  20. > do something like
  21.  
  22. >     struct FM *p = malloc (sizeof (struct FM) + n);
  23.  
  24. Agreed.
  25.  
  26. > In this situation the standard *does* allow a correctly declared
  27. > array element of the struct to be subscripted out of range, as long
  28. > as you stay within the malloc()ed area.  This has been discussed
  29. > at great length in comp.std.c not too long ago.  The only argument
  30. > that it might be illegal in this situation which was not countered
  31. > by reference to the standard amounted to saying that they must
  32. > have *intended* it to be illegal and didn't get the wording right.
  33.  
  34. Unfortunately, I wasn't in on that discussion.  But to convince me
  35. that it's legal, you'd have to find language in the standard that allows
  36. it.  I looked around a little bit, and here is what I found, in the description
  37. of pointer+integer:
  38.  
  39.     Unless both the pointer operand and the result point to
  40.     elements of the same array object, or the pointer
  41.     operand points one past the last element of an array
  42.     object and the result points to an element of the same
  43.     array object, the behavior is undefined if the result
  44.     is used as an operand of the unary * operator.
  45.  
  46. Now, let's take a look at the example again:
  47.  
  48.     struct FM {
  49.         int size;
  50.         char data[1];
  51.     };
  52.  
  53.     main()
  54.     {
  55.         struct FM *p = (struct FM *) malloc(sizeof(struct FM) + 100);
  56.         p->data[5] = '?';
  57.     }
  58.  
  59. At issue is the assignment to p->data[5].
  60.  
  61. As I see it, the question is just what p->data is.  If I look at the
  62. definition of p, I see that p->data is an array of char with one element.
  63. The way I've used it is, of course, equivalent to *(p->data+5).
  64.  
  65. That means p->data is converted to a pointer to its initial element,
  66. namely a pointer to the first (and only) element of a one-element array.
  67. [Remember this assertion].  So, we take that pointer, add 5 to it,
  68. and apply unary * to the result.  Well, the pointer operand of +
  69. points to an element of the array object, but the result does not;
  70. there is only one element and the result doesn't point there.
  71. The result of using unary * is therefore undefined.
  72.  
  73. Now, look back at the assertion I asked you to remember.  I expect
  74. that Mark Brader is going to say `But p->data isn't an array of
  75. one element, it's an array of 101 elements.  After all, when you
  76. said malloc(sizeof(struct FM + 100), you allocated enough memory
  77. for 101 elements!'
  78.  
  79. Here are two reasons I disagree:
  80.  
  81.     1. Suppose I said
  82.  
  83.         struct FM *q = (struct FM *) malloc(sizeof(struct FM) + 100);
  84.  
  85.     and later said
  86.  
  87.         *p = *q;
  88.  
  89.     Is the compiler obligated to realize that p and q actually point
  90.     to objects of type other than struct FM?  That is, is it obligated
  91.     to copy all the `extra' elements in the data array?
  92.  
  93.     2. If you declare p by saying
  94.  
  95.         struct FM *p;
  96.  
  97.     then I don't think there is any place in the standard that says
  98.     other than that *p is an lvalue of type FM.  Once you acknowledge
  99.     that *p is of type FM, I don't see how you can get away from the
  100.     p->data being anything other than a one-element array.  What I found
  101.     in the standard that talks about this is:
  102.  
  103.  
  104.         The pointer returned [by malloc or realloc] if the
  105.         allocation succeeds is suitably aligned so that it
  106.         may be assigned to a pointer to any type of object
  107.         and then used to access such an object or an array
  108.         of such objects in the space allocated (until the
  109.         space is explicitly freed or reallocated).
  110.     
  111.     It doesn't say that it may be assigned to a pointer to some
  112.     type of object and then used to access an object of some other
  113.     type.  That is, it says that the result of malloc may be
  114.     assigned to a struct FM * and then used to access an object
  115.     of type struct FM.  It says nothing about struct FM representing
  116.     a family of related types.
  117.  
  118. Another way to look at it is this.  Suppose I have a compiler that rejects:
  119.  
  120.     void f(struct FM *p)
  121.     {
  122.         p->data[5] = '?';
  123.     }
  124.  
  125. on the basis that p->data is a one-element array and you can't refer to
  126. the fifth element of a one-element array.  What part of the standard can
  127. you cite to convince me that my compiler isn't allowed to diagnose this?
  128. -- especially after the description of pointer arithmetic above?
  129. -- 
  130.                 --Andrew Koenig
  131.                   ark@europa.att.com
  132.