home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / lang / c / 11715 < prev    next >
Encoding:
Text File  |  1992-07-29  |  4.6 KB  |  111 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!gatech!hubcap!mjs
  3. From: mjs@hubcap.clemson.edu (M. J. Saltzman)
  4. Subject: Re: Pointers outside of array boundary
  5. Message-ID: <1992Jul29.183819.3662@hubcap.clemson.edu>
  6. Summary: Thanks and summary
  7. Organization: Clemson University, Clemson SC
  8. References: <1992Jul28.180945.22332@hubcap.clemson.edu>
  9. Date: Wed, 29 Jul 1992 18:38:19 GMT
  10. Lines: 99
  11.  
  12. Thanks to everyone who responded to my query about 1-based array indexing.
  13. Below is a summary of replies.  The upshot is that there *is* a machine 
  14. on which this code fails.
  15.  
  16. In article <1992Jul28.180945.22332@hubcap.clemson.edu> I wrote:
  17. >I am having an e-mail conversation with someone regarding the
  18. >_Numerical_Recipes_in_C_ practice of creating arrays with offset
  19. >indices.  The sample code in question is 
  20. >
  21. >    float x = malloc(10*sizeof(float));
  22.               ^
  23. >    --x;
  24.  
  25. Should have been *x, of course (but it wasn't my code 8^)).
  26.  
  27. >which is supposed to give an array whose elements are addressed
  28. >as x[1]..x[10].
  29. >[...]
  30. >     What could possibly go wrong if we only ever dereference 
  31. >x[1]..x[10]?
  32. >[...]
  33. >My question is: Can anyone name an existing machine on which this code
  34. >could fail, or give a really convincing hypothetical argument why it
  35. >is a bad idea?
  36. >[...]
  37. >
  38. >Also, could someone quote the relevant part of the standard?
  39. >[...]
  40.  
  41. Mark Brader (msb@sq.com) quoted the standard, and the rationale:
  42.  
  43. }It's in section 3.3.6 (ANSI numbering, 6.3.6 in ISO numbering), which
  44. }defines the operators + and -.  (The statement could have been written
  45. }as x = x - 1; and this would be equivalent; I won't trouble to cite the
  46. }parts of the standard that specify this equivalence.)  Here's the sentence:
  47. }
  48. }#  If both the pointer operand and the result point to elements of
  49. }#  the same array object, or one past the last element of the array
  50. }#  object, the evaluation shall not produce an overflow, otherwise
  51. }#  the behavior is undefined.
  52. }
  53. }"Undefined behavior" allows the program to abort, or worse.
  54.  
  55. And:
  56.  
  57. }      The "one past the end of the array" rule wasn't in K&R, but people
  58. }were in the habit of using it.  The Rationale says:
  59. }
  60. }| An important endorsement of widespread practice is the requirement
  61. }| that a pointer can always be incremented to _just_past_ the end of
  62. }| an array, with no fear of overflow or wraparound:
  63. }| 
  64. }|     SOMETYPE array[SPAN];
  65. }|     /* ... */
  66. }|     for (p = &array[0]; p < &array[SPAN]; p++)
  67. }| 
  68. }| This stipulation merely requires that every object be followed by one
  69. }| byte whose address is representable.  That byte can be the first byte
  70. }| of the next object declared[,] for all but the last object located in
  71. }| a contiguous segment of memory.  (In the example, the address &array[SPAN]
  72. }| must address a byte following the highest element of array.)  Since the
  73. }| pointer expression p+1 need not (and should not) be dereferenced, it is
  74. }| unnecessary to leave room for a complete object of size sizeof(*p).
  75. }| 
  76. }| In the case of p-1, on the other hand, an entire object _would_ have
  77. }| to be allocated prior to the array of objects that p traverses, so
  78. }| decrement loops that run off the bottom of an array may fail.  This
  79. }| restriction allows segmented architectures, for instance, to place
  80. }| objects at the start of a range of addressable memory.
  81. }
  82. }They are tacitly assuming here that a pointer to a multi-byte object
  83. }is implemented using a pointer to the first byte.  While the standard
  84. }does not actually require this, it is common practice.  Since the Rationale
  85. }is only suggesting a convenient implementation, that's all right.
  86.  
  87. Most people suggested hypothetical architectures on which performing
  88. the decrement operation could result in a trap, due to either
  89. underflow on an offset pointer or hardware-implemented range checking.
  90. But Barry Gorman (GORMAN_B@prime1.lancashire-poly.ac.uk) reports:
  91.  
  92. }I have tried your code (slightly extended) on a Pr1me '50 series.
  93. }This machine has a 'segmented' architecture, where a pointer has a segment
  94. }field and an offset field (plus a bit more). If malloc() serves up a pointer
  95. }with a zero offset (it does if you grab a full segment) then decrementing
  96. }it causes the offset to go to 0xFFFE, and decrements the segment field.
  97. }When you use an index such as x[2], only the offset field gets incremented,
  98. }and the segment field is one short, i.e. it uses the WRONG segment.
  99.  
  100. So this is a case where the decrement and increment operators don't
  101. behave as inverses, i.e. for float *x, x != --x + 1.  This seems to me
  102. to be much more insidious than trapping the decrement operator.
  103.  
  104. Anyhow, I think that clears the matter up pretty completely.  Thanks
  105. again to everyone who repiled.
  106.  
  107. -- 
  108.         Matthew Saltzman
  109.         Clemson University Math Sciences
  110.         mjs@clemson.edu
  111.