I think you should use ptrdiff_t
for the following reasons
- Indices can be negative. Therefore for a general statement, all unsigned types, including
size_t
, are unsuitable. - The type of
p2 - p1
isptrdiff_t
. Ifi == p2 - p1
, then you should be able to getp2
back byp2 == p1 + i
. Notice that*(p + i)
is equivalent top[i]
. - As another indication for this “general index type”, the type of the index that’s used by overload resolution when the builtin
operator[]
(for example, on a pointer) competes against a user-providedoperator[]
(for example vector’s) is exactly that (http://eel.is/c++draft/over.built#16):
>For every cv-qualified or cv-unqualified object type T there exist candidate operator functions of the form
T* operator+(T*, std::ptrdiff_t); T& operator[](T*, std::ptrdiff_t); T* operator-(T*, std::ptrdiff_t); T* operator+(std::ptrdiff_t, T*); T& operator[](std::ptrdiff_t, T*);
EDIT: If you have a really big array or a pointer to a really big memory portion, then my “general index type” doesn’t cut it, as it then isn’t guaranteed that you can subtract the first element’s address from the last element’s address. @Ciro’s answer should be used then https://stackoverflow.com/a/31090426/34509 . Personally I try to avoid using unsigned types for their non-ability to represent negative edge cases (loop end-values when iterating backwards for example), but this is a kind of religious debate (I’m not alone in that camp, though). In cases where using an unsigned type is required, I must put my religion aside, of course.