6.2.5.15 - http://port70.net/~nsz/c/c11/n1570.html#6.2.5p15
6.3.2.3.7 - http://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p7
B.19 - actually I think 7.20.1 is a better demonstration that these are integer types (and not, since it's never mentioned, character types) - http://port70.net/~nsz/c/c11/n1570.html#7.20.1
7.20.1.1.3 - http://port70.net/~nsz/c/c11/n1570.html#7.20.1.1p3
http://port70.net/~nsz/c/c11/n1570.html#6.2.5p4 leaves open the option for extended signed integer types, and the following paragraph provides for an unsigned integer type for each signed type, extended signed types included.
So it would be perfectly possible, if not actually very reasonable - not that this is stopping anybody at the moment - for an implementation to provide __int8, a signed 8-bit integer type that fulfils all the requirements of uint8_t, but is not a character type, and use that as uint8_t. Then, conceivably, it could fail to support the use of uint8_t pointers to alias other objects, something supported by the more usual situation of using unsigned char for uint8_t.
I'm not sure that anybody would do this, but they could. I'm rather surprised gcc doesn't do it, come to think of it, just to teach its users a lesson. Maybe I should file a bug report?
I looked briefly previously and somehow got the sense that extended types could only be larger than standard types, but this time I found that 6.3.1.1 explicitly mentions same width extended types.
Personally, I've been happy with GCC's decisions on such issues.
In C, with CHAR_BIT defined as 8, unsigned char is the only type that satisfies the requirements of uint8_t.
( It is also possible that it is defined as char, if implementation defines char to have the same range, representation, and behavior as unsigned char. In this case, char effectively becomes unsigned char, but is still a distinct type. The types are compatible (can alias).)
Now why is unsigned char the only possibility. Type uint8_t is defined to have two'2 complement, have exactly 8 bits, no padding, and be unsigned. So we need an unsigned integer type. The unsigned type that follows unsigned char in rank is unsigned short char. But this type is defined to have ranges at least from 0 to 65535. Since CHAR_BIT is 8, unsigned short int cannot be used, because it has to have more than 8 bits. As there is no type in rank before unsigned char, it remains the only possibility.
See also this suggestion that the gcc people, true to form, considered making uint8_t something other than unsigned char: https://news.ycombinator.com/item?id=10868953
Or it could use a typedef .e.g typedef __special_u8 uint8_t; where the particular compiler internally knows about __special_u8 and treats it differently from unsigned char.