According to N1570 (C11 draft) 6.5.6/8 Additive operators:
Moreover, if the expression
Ppoints to the last element
The rationale is quite simple. The compiler is not allowed to place an array at the end of memory. To illustrate, assume that we have a 16-bit machine with 16-bit pointers. The low address is 0x0000. The high address is 0xffff. If you declare char array[256] and the compiler locates array at address 0xff00, then technically the array would fit into the memory, using addresses 0xff00 thru 0xffff inclusive. However, the expression
char *endptr = &array[256]; // endptr points one past the end of the array
would be equivalent to
char *endptr = NULL; // &array[256] = 0xff00 + 0x0100 = 0x0000
Which means that the following loop would not work, since ptr will never be less than 0
for ( char *ptr = array; ptr < endptr; ptr++ )
So the sections you cited are simply lawyer-speak for, "Don't put arrays at the end of a memory region".
Historical note: the earliest x86 processors used a segmented memory scheme wherein memory addresses where specified by a 16-bit pointer register and a 16-bit segment register. The final address was computed by shifting the segment register left by 4 bits and adding to the pointer, e.g.
pointer register 1234
segment register AB00
-----
address in memory AC234
The resulting address space was 1MByte, but there were end-of-memory boundaries every 64Kbytes. That's one reason for using lawyer-speak instead of stating, "Don't put arrays at the end of memory" in plain english.