| From: Vincent Lefevre <[EMAIL PROTECTED]> | To: gcc@gcc.gnu.org | Subject: Re: Pointers in comparison expressions | | On 2005-07-17 12:55:38 -0400, Paul Koning wrote: | > Are you sayinvg that a-b is not always "guaranteed to work" when a | > and b point to elements of the same array? That sounds wrong; can | > you given an example or standards text that supports this? | | 6.5.6 Additive operators | [...] | [#9] When two pointers are subtracted, both shall point to | elements of the same array object, or one past the last | element of the array object; the result is the difference of | the subscripts of the two array elements. The size of the | result is implementation-defined, and its type (a signed | integer type) is ptrdiff_t defined in the <stddef.h> header. | If the result is not representable in an object of that | type, the behavior is undefined. In other words, if the | expressions P and Q point to, respectively, the i-th and j- | th elements of an array object, the expression (P)-(Q) has | the value i-j provided the value fits in an object of type | ptrdiff_t. [...] | | See the sentence "If the result..." and the last few words of the | next sentence.
This is true. And an abomination. But I will explain a bit more where this came from. On, for example, the PDP-11, size_t would be unsigned int (16 bits). ptrdiff_t would be signed int because making it long feels wrong -- it is too expensive and would only be more correct in an extremely rare case. That case can only come up when dealing with a char array larger than 32K. Since the maximum addressable data space was 64K, no real program would do this (except to make fools of us). So the committee felt that it was important to allow ptrdiff_t to be "too small". I suggested that ptrdiff_t should be required to be at least as large as the signed variant of size_t, but they did not accept this. So a legal implementation may make ptrdiff_t as small as signed char (recent versions of the standard mandate that PTRDIFF_MAX must be at least 64K-1; this negates the original reason for the laxity). This same logic can now be transferred to 32-bit machines. ptrdiff_t on most 32-bit machines is 32 bits, so a char array larger than 2G could allow for overflowing pointer subtraction. Since GCC knows the range of values that can be represented in ptrdiff_t, it knows whether the subtraction might overflow.