According to N1570 (C11 draft) 6.5.6/8 Additive operators:
Moreover, if the expression
Ppoints to the last element of an array object, the expression(P)+1points one past the last element of the array object, and if the expressionQpoints one past the last element of an array object, the expression(Q)-1points to the last element of the array object
Subclause 6.5.6/9 also contains:
Moreover, if the expression
Ppoints either to an element of an array object or one past the last element of an array object, and the expressionQpoints to the last element of the same array object, the expression((Q)+1)-(P)has the same value as((Q)-(P))+1and as-((P)-((Q)+1)), and has the value zero if the expressionPpoints one past the last element of the array object, even though the expression(Q)+1does not point to an element of the array object.106)
This justifies pointer's arithmetic like this to be valid:
#include <stdio.h>
int main(void)
{
    int a[3] = {0, 1, 2};
    int *P, *Q;
    P = a + 3; // one past the last element
    Q = a + 2; // last element
    printf("%td\n", ((Q)+1)-(P));
    printf("%td\n", ((Q)-(P))+1);
    printf("%td\n", -((P)-((Q)+1)));
    return 0;
}
I would expect to disallow pointing to element of array out-of-bounds, for which dereference acts as undefined behaviour (array overrun), thus it makes it potentially dangerous. Is there any rationale for this?
 
     
    