Paul Eggert wrote:
> #include <stdint.h>
> #include <stddef.h>
> #include <stdlib.h>
>
> ptrdiff_t
> diff (short *a, short *b)
> {
> return a - b;
> }
>
> int
> main (void)
> {
> size_t n = PTRDIFF_MAX / sizeof (short) + 1;
> short *x = malloc (n * sizeof (short));
> return 0 < diff (x + n, x);
> }
I can reproduce it, on Ubuntu with "gcc -m32", even with a 2.5 GB allocation:
size_t n = PTRDIFF_MAX / sizeof (short) * 1.25;
'ltrace' shows that malloc succeeds.
The code of the 'diff' function shows a signed shift:
diff:
movl 4(%esp), %eax
subl 8(%esp), %eax
sarl %eax
ret
And indeed, an unsigned shift is not possible here because the compiler
doesn't know whether to expect a >= b or a <= b.
So, the limiting factor is the pointer difference operator
ptr1 - ptr2 where sizeof (*ptr1,*ptr2) > 1.
Consequences:
* We have no problem with code that only works with indices and never does
pointer differences or pointer comparisons.
for (i = 0; i < n; i++)
do_something (&array[i]);
is better than
array_end = &array_end;
for (p = array; p < array_end; p++)
do_something (p);
But does GCC's strength-reduction optimization know this?
* We have no problem with strings, because sizeof (char) == 1.
Bruno