Signed types are the sane ones and give you error checking possibilities (negative size doesn't make sense; huge positive size may be right or an error). Unsigned types break trivial math like x < y => x-1 < y-1.
It's not so bad. It means you can be really consistent about returning error codes from every function in the exact same way. This is one of the very few things I actually like about the Win32 API. If only they used the same type of error codes in every section of the API.
Also note that C only half-heartedly supports objects larger than SIZE_MAX/2: relevant quote from http://en.cppreference.com/w/cpp/types/ptrdiff_t
"If an array is so large (greater than PTRDIFF_MAX elements, but less than SIZE_MAX bytes), that the difference between two pointers may not be representable as std::ptrdiff_t, the result of subtracting two such pointers is undefined. "