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