operator [] on pointers can be any integral expression
To be general, ptrdiff_t is technically what you want, if the intention is for data and data + i to be any two arbitrary pointers in either other and to arbitrary blocks of memory, since ptrdiff_t is defined as a signed type for holding the difference between two pointers (however, it's not guaranteed to not overflow: ptrdiff_t on machines with 32-bit pointers is typically 32-bit, not the next signed integral size higher)
In std::vector<T>, size_t is (typically) used, because std::vector has the additional restriction that the pointer points to the beginning of a block and indexing is only allowed within the allocated block, which cannot be larger than size_t by definition, and no negative indicies are allowed. size_t can be smaller than ptrdiff_t or uintptr_t (the unsigned integral type that can hold a pointer), for example on segmented architectures in which memory allocations are limited to one segment but pointers are not.
Now, if the intention is that data and data + i are part of the same block of memory but not necessarily such that data + i >= data, then I don't think there's an exact fit natural data type (i.e. a signed counterpart to size_t...I could be wrong) in Standard C++ (ssize_t is a POSIX extension), but you can go with ptrdiff_t since it's guaranteed to be at least as large as what you want.
There's no guarantee that sizeof(long) or sizeof(int) have any relationship with sizeof(ptrdiff_t) or sizeof(size_t)...assuming so can lead to nasty bugs.
EDIT: Technically, there's no portable way to obtain data and i such that data and data + i are both valid pointers and point to different objects in different allocation blocks, since the standard only guarantees that pointer arithmetic is well-defined within an allocated block, so if you're relying on doing so then your program is non-portable anyway. (Not that it won't work, in most cases...)
size_tis a natural choicesizeof(integral_type) == sizeof (pointer). Solong, probably.