it's undefined because you have no idea what other functions will do with it.
Admittedly I just found out that it's undefined 45 minutes ago, but I'm pretty sure that's not the reason why. By that logic copying the pointer to a different variable or passing it to a function that we defined ourselves would not invoke UB because then we would know what's being done with it. But according to this (page 49, lines 14+) any use of an illegal pointer invokes UB.
Also we do know what printf does with its arguments. Since the standard does not mandate that the argument for %d shall be a pointer that's legal to dereference (which it doesn't, since the argument for %d shouldn't even be a pointer), any implementation that does dereference the argument would be in violation of the standard. Likewise the standard does not mandate that %p (which the OP should be using) dereferences its argument and therefore it won't. In particular it is legal to do printf("%p", arr+n) where arr is an array of size n. If printf could potentially dereference an argument for %p, that would not be legal.
As a sidenote, there's another reason why the code invokes undefined behavior: %d expects an integer, but is given a pointer.
6.2.4 Storage durations of objects
The lifetime of an object is the portion of program execution during which storage is
guaranteed to be reserved for it. An object exists, has a constant address,25) and retains
its last-stored value throughout its lifetime.26) If an object is referred to outside of its
lifetime, the behavior is undeﬁned. The value of a pointer becomes indeterminate when
the object it points to reaches the end of its lifetime.
188.8.131.52 Pointers (Point 6)
Any pointer type may be converted to an integer type. Except as previously speciﬁed, the
result is implementation-deﬁned. If the result cannot be represented in the integer type,
the behavior is undeﬁned. The result need not be in the range of values of any integer
7.1.4 Use of library functions
Each of the following statements applies unless explicitly stated otherwise in the detailed
descriptions that follow: If an argument to a function has an invalid value (such as a value
outside the domain of the function, or a pointer outside the address space of the program,
or a null pointer, orapointer to non-modiﬁable storage when the corresponding
parameter is not const-qualiﬁed) or a type (after promotion) not expected by a function
with variable number of arguments, the behavior is undeﬁned.