home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / lang / c / 17031 < prev    next >
Encoding:
Internet Message Format  |  1992-11-23  |  5.8 KB

  1. Xref: sparky comp.lang.c:17031 comp.std.c:3056
  2. Newsgroups: comp.lang.c,comp.std.c
  3. Path: sparky!uunet!munnari.oz.au!cs.mu.OZ.AU!munta.cs.mu.OZ.AU!fjh
  4. From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
  5. Subject: Struct hack (was: Re: Is this ANSI?)
  6. Message-ID: <9232902.26984@mulga.cs.mu.OZ.AU>
  7. Followup-To: comp.std.c
  8. Sender: news@cs.mu.OZ.AU
  9. Organization: Computer Science, University of Melbourne, Australia
  10. References: <9eRguB1w165w@quest.UUCP> <24238@alice.att.com> <1992Nov21.125038.26244@sq.sq.com> <24270@alice.att.com>
  11. Date: Mon, 23 Nov 1992 15:48:23 GMT
  12. Lines: 136
  13.  
  14. ark@alice.att.com (Andrew Koenig) writes:
  15.  
  16. >... to convince me
  17. >that it's legal, you'd have to find language in the standard that allows
  18. >it.
  19.  
  20. Sure, but to convince me that it's illegal, you'd have to find language
  21. in the standard that disallows it :-)
  22.  
  23. >I looked around a little bit, and here is what I found, in the description
  24. >of pointer+integer:
  25. >
  26. >    Unless both the pointer operand and the result point to
  27. >    elements of the same array object, or the pointer
  28. >    operand points one past the last element of an array
  29. >    object and the result points to an element of the same
  30. >    array object, the behavior is undefined if the result
  31. >    is used as an operand of the unary * operator.
  32.  
  33. The way I read it, this sentence is implicitly existentially qualified
  34. with respect to the array object. That is, it means "Unless there
  35. exists some array object which is pointed to by both the pointer
  36. operand and the result, ...".  This reading is supported
  37. by the use of the phrase "the last element of *an* array object".
  38.  
  39. >Now, let's take a look at the example again:
  40. [example omitted]
  41. >At issue is the assignment to p->data[5].
  42. >
  43. >As I see it, the question is just what p->data is.  If I look at the
  44. >definition of p, I see that p->data is an array of char with one element.
  45. >The way I've used it is, of course, equivalent to *(p->data+5).
  46. >
  47. >That means p->data is converted to a pointer to its initial element,
  48. >namely a pointer to the first (and only) element of a one-element array.
  49. >[Remember this assertion].
  50.  
  51. This is not the *only* thing that p->data points to.
  52.  
  53. >So, we take that pointer, add 5 to it,
  54. >and apply unary * to the result.  Well, the pointer operand of +
  55. >points to an element of the array object, but the result does not;
  56. >there is only one element and the result doesn't point there.
  57. >The result of using unary * is therefore undefined.
  58.  
  59. No, because *there exists* an array object for which
  60. both the pointer operand and the result point to elements of that
  61. array object.
  62.  
  63. >Now, look back at the assertion I asked you to remember.  I expect
  64. >that Mark Brader is going to say `But p->data isn't an array of
  65. >one element, it's an array of 101 elements.  After all, when you
  66. >said malloc(sizeof(struct FM + 100), you allocated enough memory
  67. >for 101 elements!'
  68. >
  69. >Here are two reasons I disagree:
  70. >
  71. >    1. Suppose I said
  72. >
  73. >        struct FM *q = (struct FM *) malloc(sizeof(struct FM) + 100);
  74. >
  75. >    and later said
  76. >
  77. >        *p = *q;
  78. >
  79. >    Is the compiler obligated to realize that p and q actually point
  80. >    to objects of type other than struct FM?  That is, is it obligated
  81. >    to copy all the `extra' elements in the data array?
  82.  
  83. No; but I don't see how this is directly relevant.
  84.  
  85. >    2. If you declare p by saying
  86. >
  87. >        struct FM *p;
  88. >
  89. >    then I don't think there is any place in the standard that says
  90. >    other than that *p is an lvalue of type FM.  Once you acknowledge
  91. >    that *p is of type FM, I don't see how you can get away from the
  92. >    p->data being anything other than a one-element array.
  93.  
  94. As I see it, the question is not what is the type of p->data, the question is
  95. rather what does the pointer (char *)p->data point to, and the answer is
  96. that it points to a one-element array and *also* points into a larger array.
  97.  
  98. >    What I found
  99. >    in the standard that talks about this is:
  100. >
  101. >        The pointer returned [by malloc or realloc] if the
  102. >        allocation succeeds is suitably aligned so that it
  103. >        may be assigned to a pointer to any type of object
  104. >        and then used to access such an object or an array
  105. >        of such objects in the space allocated (until the
  106. >        space is explicitly freed or reallocated).
  107. >    
  108. >    It doesn't say that it may be assigned to a pointer to some
  109. >    type of object and then used to access an object of some other
  110. >    type.
  111.  
  112. No, but it doesn't say that this is *not* allowed, either.
  113.  
  114. >Another way to look at it is this.  Suppose I have a compiler that rejects:
  115. >
  116. >    void f(struct FM *p)
  117. >    {
  118. >        p->data[5] = '?';
  119. >    }
  120. >
  121. >on the basis that p->data is a one-element array and you can't refer to
  122. >the fifth element of a one-element array.  What part of the standard can
  123. >you cite to convince me that my compiler isn't allowed to diagnose this?
  124. >-- especially after the description of pointer arithmetic above?
  125.  
  126. As I said before, the fact that p->data is a one-element array doesn't
  127. imply that (char *)p->data does not also point to some other array which does
  128. have a element at the position *(p->data+5), and if it does, the
  129. statement p->data[5] = '?' should be quite legal. Obviously the compiler
  130. can't reject a program because it *might* contain a statement whose behaviour
  131. is undefined. (By the way: exactly when *is* a compiler allowed to reject
  132. a program?)
  133.  
  134. Clearly the statement is syntactically correct.
  135. I believe that the onus is on those who believe the statement to be illegal to
  136. cite supporting evidence, and I do not believe that what you have just
  137. cited is convincing.
  138.  
  139. P.S. I haven't read the standard myself and I could well be wrong :-)
  140.      I am just arguing a point of view, to see what the response
  141.      from supporters of the opposing point of view will be.
  142.      
  143. P.P.S. Followups to comp.std.c.
  144.  
  145. -- 
  146. Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
  147. This .signature virus is a self-referential statement that is true - but 
  148. you will only be able to consistently believe it if you copy it to your own
  149. .signature file!
  150.