You aren’t actually subtracting the array. You are subtracting the pointer address of the beginning of the array.
This is because upper_bound() does not take an array as argument, so the compiler “decays” the array type to a pointer type, with the value pointing to the first element of the array.
This conveniently works, since upper_bound() expects an iterator, and a pointer is an iterator. (Iterators were designed to pretend to be pointers, so using an iterator and using a pointer is very much the same kind of code.)
After that everything is pointer (iterator) arithmetic.
Subtracting one pointer from another, gives you the "distance" between those two pointers, measured in terms of the type of object those pointers point to.
As Duthomas says, this is basic pointer arithmetic, and should be covered by your textbook.